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
|
||||
=======================
|
||||
|
||||
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)
|
||||
-------
|
||||
|
||||
@@ -12,6 +25,7 @@ v6.16.0 (2020-08-01)
|
||||
* Added comparisons (`>`, `>=`, `==`, `!=`, `<`, and `<=`) between `JsonVariant`s
|
||||
* Added string deduplication (issue #1303)
|
||||
* Added `JsonString::operator!=`
|
||||
* Added wildcard key (`*`) for filters (issue #1309)
|
||||
* Set `ARDUINOJSON_DECODE_UNICODE` to `1` by default
|
||||
* Fixed `copyArray()` not working with `String`, `ElementProxy`, and `MemberProxy`
|
||||
* 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://travis-ci.org/bblanchon/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;
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
inline void arrayAccept(const CollectionData *arr, Visitor &visitor) {
|
||||
template <typename TVisitor>
|
||||
inline typename TVisitor::result_type arrayAccept(const CollectionData *arr,
|
||||
TVisitor &visitor) {
|
||||
if (arr)
|
||||
visitor.visitArray(*arr);
|
||||
return visitor.visitArray(*arr);
|
||||
else
|
||||
visitor.visitNull();
|
||||
return visitor.visitNull();
|
||||
}
|
||||
|
||||
inline bool arrayEquals(const CollectionData *lhs, const CollectionData *rhs) {
|
||||
|
||||
@@ -27,9 +27,9 @@ class ArrayRefBase {
|
||||
return VariantConstRef(reinterpret_cast<const VariantData*>(data));
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
FORCE_INLINE void accept(Visitor& visitor) const {
|
||||
arrayAccept(_data, visitor);
|
||||
template <typename TVisitor>
|
||||
FORCE_INLINE typename TVisitor::result_type accept(TVisitor& visitor) const {
|
||||
return arrayAccept(_data, visitor);
|
||||
}
|
||||
|
||||
FORCE_INLINE bool isNull() const {
|
||||
|
||||
@@ -98,8 +98,8 @@ class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
|
||||
return getOrAddUpstreamElement().set(value);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void accept(Visitor& visitor) const {
|
||||
template <typename TVisitor>
|
||||
typename TVisitor::result_type accept(TVisitor& visitor) const {
|
||||
return getUpstreamElement().accept(visitor);
|
||||
}
|
||||
|
||||
|
||||
@@ -65,40 +65,61 @@ inline bool copyArray(T (&src)[N1][N2], JsonDocument& dst) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class ArrayCopier1D {
|
||||
class ArrayCopier1D : public Visitor<size_t> {
|
||||
public:
|
||||
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();
|
||||
|
||||
while (slot != 0 && _size < _capacity) {
|
||||
_destination[_size++] = variantAs<T>(slot->data());
|
||||
while (slot != 0 && size < _capacity) {
|
||||
_destination[size++] = variantAs<T>(slot->data());
|
||||
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 {
|
||||
return _size;
|
||||
size_t visitObject(const CollectionData&) {
|
||||
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:
|
||||
T* _destination;
|
||||
size_t _capacity;
|
||||
size_t _size;
|
||||
};
|
||||
|
||||
template <typename T, size_t N1, size_t N2>
|
||||
class ArrayCopier2D {
|
||||
class ArrayCopier2D : public Visitor<void> {
|
||||
public:
|
||||
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>
|
||||
inline size_t copyArray(const TSource& src, T* dst, size_t len) {
|
||||
ArrayCopier1D<T> copier(dst, len);
|
||||
src.accept(copier);
|
||||
return copier.result();
|
||||
|
||||
return src.accept(copier);
|
||||
}
|
||||
|
||||
// Copy a JsonArray to a 2D array
|
||||
|
||||
@@ -230,3 +230,8 @@
|
||||
#define ARDUINOJSON_DEBUG 0
|
||||
#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
|
||||
|
||||
#include <ArduinoJson/Namespace.hpp>
|
||||
#include <ArduinoJson/Polyfills/preprocessor.hpp>
|
||||
#include <ArduinoJson/Polyfills/static_array.hpp>
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#include <ostream>
|
||||
@@ -20,6 +22,7 @@ class DeserializationError {
|
||||
public:
|
||||
enum Code {
|
||||
Ok,
|
||||
EmptyInput,
|
||||
IncompleteInput,
|
||||
InvalidInput,
|
||||
NoMemory,
|
||||
@@ -77,24 +80,31 @@ class DeserializationError {
|
||||
}
|
||||
|
||||
const char* c_str() const {
|
||||
switch (_code) {
|
||||
case Ok:
|
||||
return "Ok";
|
||||
case TooDeep:
|
||||
return "TooDeep";
|
||||
case NoMemory:
|
||||
return "NoMemory";
|
||||
case InvalidInput:
|
||||
return "InvalidInput";
|
||||
case IncompleteInput:
|
||||
return "IncompleteInput";
|
||||
case NotSupported:
|
||||
return "NotSupported";
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
static const char* messages[] = {
|
||||
"Ok", "EmptyInput", "IncompleteInput", "InvalidInput",
|
||||
"NoMemory", "NotSupported", "TooDeep"};
|
||||
ARDUINOJSON_ASSERT(static_cast<size_t>(_code) <
|
||||
sizeof(messages) / sizeof(messages[0]));
|
||||
return messages[_code];
|
||||
}
|
||||
|
||||
#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:
|
||||
Code _code;
|
||||
};
|
||||
|
||||
@@ -33,7 +33,7 @@ class Filter {
|
||||
if (_variant == true) // "true" means "allow recursively"
|
||||
return *this;
|
||||
else
|
||||
return Filter(_variant[key]);
|
||||
return Filter(_variant[key] | _variant["*"]);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <Stream.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
|
||||
@@ -32,8 +32,9 @@ deserialize(JsonDocument &doc, const TString &input, NestingLimit nestingLimit,
|
||||
TFilter filter) {
|
||||
Reader<TString> reader(input);
|
||||
doc.clear();
|
||||
return makeDeserializer<TDeserializer>(doc.memoryPool(), reader,
|
||||
makeStringStorage(input))
|
||||
return makeDeserializer<TDeserializer>(
|
||||
doc.memoryPool(), reader,
|
||||
makeStringStorage(input, doc.memoryPool()))
|
||||
.parse(doc.data(), filter, nestingLimit);
|
||||
}
|
||||
//
|
||||
@@ -47,8 +48,9 @@ DeserializationError deserialize(JsonDocument &doc, TChar *input,
|
||||
TFilter filter) {
|
||||
BoundedReader<TChar *> reader(input, inputSize);
|
||||
doc.clear();
|
||||
return makeDeserializer<TDeserializer>(doc.memoryPool(), reader,
|
||||
makeStringStorage(input))
|
||||
return makeDeserializer<TDeserializer>(
|
||||
doc.memoryPool(), reader,
|
||||
makeStringStorage(input, doc.memoryPool()))
|
||||
.parse(doc.data(), filter, nestingLimit);
|
||||
}
|
||||
//
|
||||
@@ -60,8 +62,9 @@ DeserializationError deserialize(JsonDocument &doc, TStream &input,
|
||||
NestingLimit nestingLimit, TFilter filter) {
|
||||
Reader<TStream> reader(input);
|
||||
doc.clear();
|
||||
return makeDeserializer<TDeserializer>(doc.memoryPool(), reader,
|
||||
makeStringStorage(input))
|
||||
return makeDeserializer<TDeserializer>(
|
||||
doc.memoryPool(), reader,
|
||||
makeStringStorage(input, doc.memoryPool()))
|
||||
.parse(doc.data(), filter, nestingLimit);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class JsonDocument : public Visitable {
|
||||
public:
|
||||
template <typename Visitor>
|
||||
void accept(Visitor& visitor) const {
|
||||
template <typename TVisitor>
|
||||
typename TVisitor::result_type accept(TVisitor& visitor) const {
|
||||
return getVariant().accept(visitor);
|
||||
}
|
||||
|
||||
@@ -48,6 +48,10 @@ class JsonDocument : public Visitable {
|
||||
return _pool.size();
|
||||
}
|
||||
|
||||
bool overflowed() const {
|
||||
return _pool.overflowed();
|
||||
}
|
||||
|
||||
size_t nesting() const {
|
||||
return _data.nesting();
|
||||
}
|
||||
@@ -81,6 +85,7 @@ class JsonDocument : public Visitable {
|
||||
return _pool;
|
||||
}
|
||||
|
||||
// for internal use only
|
||||
VariantData& data() {
|
||||
return _data;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ class JsonDeserializer {
|
||||
JsonDeserializer(MemoryPool &pool, TReader reader,
|
||||
TStringStorage stringStorage)
|
||||
: _stringStorage(stringStorage),
|
||||
_foundSomething(false),
|
||||
_latch(reader),
|
||||
_pool(&pool),
|
||||
_error(DeserializationError::Ok) {}
|
||||
@@ -34,7 +35,7 @@ class JsonDeserializer {
|
||||
|
||||
if (!_error && _latch.last() != 0 && !variant.isEnclosed()) {
|
||||
// We don't detect trailing characters earlier, so we need to check now
|
||||
_error = DeserializationError::InvalidInput;
|
||||
return DeserializationError::InvalidInput;
|
||||
}
|
||||
|
||||
return _error;
|
||||
@@ -241,7 +242,7 @@ class JsonDeserializer {
|
||||
if (!variant) {
|
||||
// Save key in memory pool.
|
||||
// This MUST be done before adding the slot.
|
||||
key = _stringStorage.save(_pool);
|
||||
key = _stringStorage.save();
|
||||
|
||||
// Allocate slot in object
|
||||
VariantSlot *slot = object.addSlot(_pool);
|
||||
@@ -334,7 +335,7 @@ class JsonDeserializer {
|
||||
}
|
||||
|
||||
bool parseKey() {
|
||||
_stringStorage.startString(_pool);
|
||||
_stringStorage.startString();
|
||||
if (isQuote(current())) {
|
||||
return parseQuotedString();
|
||||
} else {
|
||||
@@ -343,12 +344,11 @@ class JsonDeserializer {
|
||||
}
|
||||
|
||||
bool parseStringValue(VariantData &variant) {
|
||||
_stringStorage.startString(_pool);
|
||||
_stringStorage.startString();
|
||||
if (!parseQuotedString())
|
||||
return false;
|
||||
const char *value = _stringStorage.save(_pool);
|
||||
variant.setString(make_not_null(value),
|
||||
typename TStringStorage::storage_policy());
|
||||
const char *value = _stringStorage.save();
|
||||
variant.setStringPointer(value, typename TStringStorage::storage_policy());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -499,26 +499,12 @@ class JsonDeserializer {
|
||||
return true;
|
||||
}
|
||||
|
||||
ParsedNumber<Float, UInt> num;
|
||||
parseNumber<Float, UInt>(_buffer, num);
|
||||
|
||||
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;
|
||||
if (!parseNumber(_buffer, result)) {
|
||||
_error = DeserializationError::InvalidInput;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool skipNumericValue() {
|
||||
@@ -574,7 +560,8 @@ class JsonDeserializer {
|
||||
switch (current()) {
|
||||
// end of string
|
||||
case '\0':
|
||||
_error = DeserializationError::IncompleteInput;
|
||||
_error = _foundSomething ? DeserializationError::IncompleteInput
|
||||
: DeserializationError::EmptyInput;
|
||||
return false;
|
||||
|
||||
// spaces
|
||||
@@ -634,12 +621,14 @@ class JsonDeserializer {
|
||||
#endif
|
||||
|
||||
default:
|
||||
_foundSomething = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TStringStorage _stringStorage;
|
||||
bool _foundSomething;
|
||||
Latch<TReader> _latch;
|
||||
MemoryPool *_pool;
|
||||
char _buffer[64]; // using a member instead of a local variable because it
|
||||
@@ -648,47 +637,60 @@ class JsonDeserializer {
|
||||
DeserializationError _error;
|
||||
};
|
||||
|
||||
//
|
||||
// deserializeJson(JsonDocument&, const std::string&, ...)
|
||||
template <typename TInput>
|
||||
//
|
||||
// ... = NestingLimit
|
||||
template <typename TString>
|
||||
DeserializationError deserializeJson(
|
||||
JsonDocument &doc, const TInput &input,
|
||||
JsonDocument &doc, const TString &input,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit,
|
||||
AllowAllFilter());
|
||||
}
|
||||
template <typename TInput>
|
||||
// ... = Filter, NestingLimit
|
||||
template <typename TString>
|
||||
DeserializationError deserializeJson(
|
||||
JsonDocument &doc, const TInput &input, Filter filter,
|
||||
JsonDocument &doc, const TString &input, Filter filter,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
||||
}
|
||||
template <typename TInput>
|
||||
DeserializationError deserializeJson(JsonDocument &doc, const TInput &input,
|
||||
// ... = NestingLimit, Filter
|
||||
template <typename TString>
|
||||
DeserializationError deserializeJson(JsonDocument &doc, const TString &input,
|
||||
NestingLimit nestingLimit, Filter 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(
|
||||
JsonDocument &doc, TInput &input,
|
||||
JsonDocument &doc, TStream &input,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit,
|
||||
AllowAllFilter());
|
||||
}
|
||||
template <typename TInput>
|
||||
// ... = Filter, NestingLimit
|
||||
template <typename TStream>
|
||||
DeserializationError deserializeJson(
|
||||
JsonDocument &doc, TInput &input, Filter filter,
|
||||
JsonDocument &doc, TStream &input, Filter filter,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
||||
}
|
||||
template <typename TInput>
|
||||
DeserializationError deserializeJson(JsonDocument &doc, TInput &input,
|
||||
// ... = NestingLimit, Filter
|
||||
template <typename TStream>
|
||||
DeserializationError deserializeJson(JsonDocument &doc, TStream &input,
|
||||
NestingLimit nestingLimit, Filter filter) {
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
||||
}
|
||||
|
||||
//
|
||||
// deserializeJson(JsonDocument&, char*, ...)
|
||||
//
|
||||
// ... = NestingLimit
|
||||
template <typename TChar>
|
||||
DeserializationError deserializeJson(
|
||||
JsonDocument &doc, TChar *input,
|
||||
@@ -696,19 +698,24 @@ DeserializationError deserializeJson(
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit,
|
||||
AllowAllFilter());
|
||||
}
|
||||
// ... = Filter, NestingLimit
|
||||
template <typename TChar>
|
||||
DeserializationError deserializeJson(
|
||||
JsonDocument &doc, TChar *input, Filter filter,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
||||
}
|
||||
// ... = NestingLimit, Filter
|
||||
template <typename TChar>
|
||||
DeserializationError deserializeJson(JsonDocument &doc, TChar *input,
|
||||
NestingLimit nestingLimit, Filter filter) {
|
||||
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
|
||||
}
|
||||
|
||||
//
|
||||
// deserializeJson(JsonDocument&, char*, size_t, ...)
|
||||
//
|
||||
// ... = NestingLimit
|
||||
template <typename TChar>
|
||||
DeserializationError deserializeJson(
|
||||
JsonDocument &doc, TChar *input, size_t inputSize,
|
||||
@@ -716,6 +723,7 @@ DeserializationError deserializeJson(
|
||||
return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit,
|
||||
AllowAllFilter());
|
||||
}
|
||||
// ... = Filter, NestingLimit
|
||||
template <typename TChar>
|
||||
DeserializationError deserializeJson(
|
||||
JsonDocument &doc, TChar *input, size_t inputSize, Filter filter,
|
||||
@@ -723,6 +731,7 @@ DeserializationError deserializeJson(
|
||||
return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit,
|
||||
filter);
|
||||
}
|
||||
// ... = NestingLimit, Filter
|
||||
template <typename TChar>
|
||||
DeserializationError deserializeJson(JsonDocument &doc, TChar *input,
|
||||
size_t inputSize,
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TWriter>
|
||||
class JsonSerializer {
|
||||
class JsonSerializer : public Visitor<size_t> {
|
||||
public:
|
||||
JsonSerializer(TWriter writer) : _formatter(writer) {}
|
||||
|
||||
FORCE_INLINE void visitArray(const CollectionData &array) {
|
||||
FORCE_INLINE size_t visitArray(const CollectionData &array) {
|
||||
write('[');
|
||||
|
||||
VariantSlot *slot = array.head();
|
||||
@@ -32,9 +32,10 @@ class JsonSerializer {
|
||||
}
|
||||
|
||||
write(']');
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
void visitObject(const CollectionData &object) {
|
||||
size_t visitObject(const CollectionData &object) {
|
||||
write('{');
|
||||
|
||||
VariantSlot *slot = object.head();
|
||||
@@ -52,41 +53,49 @@ class JsonSerializer {
|
||||
}
|
||||
|
||||
write('}');
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
void visitFloat(Float value) {
|
||||
size_t visitFloat(Float value) {
|
||||
_formatter.writeFloat(value);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
void visitString(const char *value) {
|
||||
size_t visitString(const char *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);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
void visitNegativeInteger(UInt value) {
|
||||
size_t visitNegativeInteger(UInt value) {
|
||||
_formatter.writeNegativeInteger(value);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
void visitPositiveInteger(UInt value) {
|
||||
size_t visitPositiveInteger(UInt value) {
|
||||
_formatter.writePositiveInteger(value);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
void visitBoolean(bool value) {
|
||||
size_t visitBoolean(bool value) {
|
||||
_formatter.writeBoolean(value);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
void visitNull() {
|
||||
size_t visitNull() {
|
||||
_formatter.writeRaw("null");
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
protected:
|
||||
size_t bytesWritten() const {
|
||||
return _formatter.bytesWritten();
|
||||
}
|
||||
|
||||
protected:
|
||||
void write(char c) {
|
||||
_formatter.writeRaw(c);
|
||||
}
|
||||
|
||||
@@ -18,44 +18,48 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
|
||||
public:
|
||||
PrettyJsonSerializer(TWriter &writer) : base(writer), _nesting(0) {}
|
||||
|
||||
void visitArray(const CollectionData &array) {
|
||||
size_t visitArray(const CollectionData &array) {
|
||||
VariantSlot *slot = array.head();
|
||||
if (!slot)
|
||||
return base::write("[]");
|
||||
if (slot) {
|
||||
base::write("[\r\n");
|
||||
_nesting++;
|
||||
while (slot != 0) {
|
||||
indent();
|
||||
slot->data()->accept(*this);
|
||||
|
||||
base::write("[\r\n");
|
||||
_nesting++;
|
||||
while (slot != 0) {
|
||||
slot = slot->next();
|
||||
base::write(slot ? ",\r\n" : "\r\n");
|
||||
}
|
||||
_nesting--;
|
||||
indent();
|
||||
slot->data()->accept(*this);
|
||||
|
||||
slot = slot->next();
|
||||
base::write(slot ? ",\r\n" : "\r\n");
|
||||
base::write("]");
|
||||
} else {
|
||||
base::write("[]");
|
||||
}
|
||||
_nesting--;
|
||||
indent();
|
||||
base::write("]");
|
||||
return this->bytesWritten();
|
||||
}
|
||||
|
||||
void visitObject(const CollectionData &object) {
|
||||
size_t visitObject(const CollectionData &object) {
|
||||
VariantSlot *slot = object.head();
|
||||
if (!slot)
|
||||
return base::write("{}");
|
||||
if (slot) {
|
||||
base::write("{\r\n");
|
||||
_nesting++;
|
||||
while (slot != 0) {
|
||||
indent();
|
||||
base::visitString(slot->key());
|
||||
base::write(": ");
|
||||
slot->data()->accept(*this);
|
||||
|
||||
base::write("{\r\n");
|
||||
_nesting++;
|
||||
while (slot != 0) {
|
||||
slot = slot->next();
|
||||
base::write(slot ? ",\r\n" : "\r\n");
|
||||
}
|
||||
_nesting--;
|
||||
indent();
|
||||
base::visitString(slot->key());
|
||||
base::write(": ");
|
||||
slot->data()->accept(*this);
|
||||
|
||||
slot = slot->next();
|
||||
base::write(slot ? ",\r\n" : "\r\n");
|
||||
base::write("}");
|
||||
} else {
|
||||
base::write("{}");
|
||||
}
|
||||
_nesting--;
|
||||
indent();
|
||||
base::write("}");
|
||||
return this->bytesWritten();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -12,17 +12,18 @@
|
||||
#include <ArduinoJson/Numbers/Integer.hpp>
|
||||
#include <ArduinoJson/Polyfills/assert.hpp>
|
||||
#include <ArduinoJson/Polyfills/attributes.hpp>
|
||||
#include <ArduinoJson/Serialization/CountingDecorator.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TWriter>
|
||||
class TextFormatter {
|
||||
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.
|
||||
size_t bytesWritten() const {
|
||||
return _length;
|
||||
return _writer.count();
|
||||
}
|
||||
|
||||
void writeBoolean(bool value) {
|
||||
@@ -128,28 +129,28 @@ class TextFormatter {
|
||||
}
|
||||
|
||||
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) {
|
||||
_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) {
|
||||
_length += _writer.write(reinterpret_cast<const uint8_t *>(begin),
|
||||
static_cast<size_t>(end - begin));
|
||||
_writer.write(reinterpret_cast<const uint8_t *>(begin),
|
||||
static_cast<size_t>(end - begin));
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
void writeRaw(const char (&s)[N]) {
|
||||
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), N - 1);
|
||||
_writer.write(reinterpret_cast<const uint8_t *>(s), N - 1);
|
||||
}
|
||||
void writeRaw(char c) {
|
||||
_length += _writer.write(static_cast<uint8_t>(c));
|
||||
_writer.write(static_cast<uint8_t>(c));
|
||||
}
|
||||
|
||||
protected:
|
||||
TWriter _writer;
|
||||
CountingDecorator<TWriter> _writer;
|
||||
size_t _length;
|
||||
|
||||
private:
|
||||
|
||||
@@ -5,13 +5,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Memory/Alignment.hpp>
|
||||
#include <ArduinoJson/Memory/StringSlot.hpp>
|
||||
#include <ArduinoJson/Polyfills/assert.hpp>
|
||||
#include <ArduinoJson/Polyfills/mpl/max.hpp>
|
||||
#include <ArduinoJson/Variant/VariantSlot.hpp>
|
||||
|
||||
#include <string.h> // memmove
|
||||
|
||||
#define JSON_STRING_SIZE(SIZE) (SIZE + 1)
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
// _begin _end
|
||||
@@ -28,7 +29,8 @@ class MemoryPool {
|
||||
: _begin(buf),
|
||||
_left(buf),
|
||||
_right(buf ? buf + capa : 0),
|
||||
_end(buf ? buf + capa : 0) {
|
||||
_end(buf ? buf + capa : 0),
|
||||
_overflowed(false) {
|
||||
ARDUINOJSON_ASSERT(isAligned(_begin));
|
||||
ARDUINOJSON_ASSERT(isAligned(_right));
|
||||
ARDUINOJSON_ASSERT(isAligned(_end));
|
||||
@@ -47,6 +49,10 @@ class MemoryPool {
|
||||
return size_t(_left - _begin + _end - _right);
|
||||
}
|
||||
|
||||
bool overflowed() const {
|
||||
return _overflowed;
|
||||
}
|
||||
|
||||
VariantSlot* allocVariant() {
|
||||
return allocRight<VariantSlot>();
|
||||
}
|
||||
@@ -90,9 +96,14 @@ class MemoryPool {
|
||||
return str;
|
||||
}
|
||||
|
||||
void markAsOverflowed() {
|
||||
_overflowed = true;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_left = _begin;
|
||||
_right = _end;
|
||||
_overflowed = false;
|
||||
}
|
||||
|
||||
bool canAlloc(size_t bytes) const {
|
||||
@@ -143,10 +154,6 @@ class MemoryPool {
|
||||
}
|
||||
|
||||
private:
|
||||
StringSlot* allocStringSlot() {
|
||||
return allocRight<StringSlot>();
|
||||
}
|
||||
|
||||
void checkInvariants() {
|
||||
ARDUINOJSON_ASSERT(_begin <= _left);
|
||||
ARDUINOJSON_ASSERT(_left <= _right);
|
||||
@@ -174,8 +181,10 @@ class MemoryPool {
|
||||
#endif
|
||||
|
||||
char* allocString(size_t n) {
|
||||
if (!canAlloc(n))
|
||||
if (!canAlloc(n)) {
|
||||
_overflowed = true;
|
||||
return 0;
|
||||
}
|
||||
char* s = _left;
|
||||
_left += n;
|
||||
checkInvariants();
|
||||
@@ -188,13 +197,16 @@ class MemoryPool {
|
||||
}
|
||||
|
||||
void* allocRight(size_t bytes) {
|
||||
if (!canAlloc(bytes))
|
||||
if (!canAlloc(bytes)) {
|
||||
_overflowed = true;
|
||||
return 0;
|
||||
}
|
||||
_right -= bytes;
|
||||
return _right;
|
||||
}
|
||||
|
||||
char *_begin, *_left, *_right, *_end;
|
||||
bool _overflowed;
|
||||
};
|
||||
|
||||
} // 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 {
|
||||
|
||||
template <typename TResult>
|
||||
struct Visitor {
|
||||
typedef TResult result_type;
|
||||
};
|
||||
|
||||
struct Visitable {
|
||||
// template<Visitor>
|
||||
// void accept(Visitor&) const;
|
||||
|
||||
@@ -21,121 +21,244 @@ class MsgPackDeserializer {
|
||||
: _pool(&pool),
|
||||
_reader(reader),
|
||||
_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) {
|
||||
parseVariant(variant, nestingLimit);
|
||||
return _error;
|
||||
parseVariant(variant, filter, nestingLimit);
|
||||
return _foundSomething ? _error : DeserializationError::EmptyInput;
|
||||
}
|
||||
|
||||
private:
|
||||
bool parseVariant(VariantData &variant, NestingLimit nestingLimit) {
|
||||
uint8_t code;
|
||||
if (!readByte(code)) {
|
||||
_error = DeserializationError::IncompleteInput;
|
||||
// Prevent VS warning "assignment operator could not be generated"
|
||||
MsgPackDeserializer &operator=(const MsgPackDeserializer &);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if ((code & 0x80) == 0) {
|
||||
variant.setUnsignedInteger(code);
|
||||
return true;
|
||||
}
|
||||
_foundSomething = true;
|
||||
|
||||
if ((code & 0xe0) == 0xe0) {
|
||||
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);
|
||||
}
|
||||
bool allowValue = filter.allowValue();
|
||||
|
||||
switch (code) {
|
||||
case 0xc0:
|
||||
// already null
|
||||
return true;
|
||||
|
||||
case 0xc1:
|
||||
return invalidInput();
|
||||
|
||||
case 0xc2:
|
||||
variant.setBoolean(false);
|
||||
if (allowValue)
|
||||
variant.setBoolean(false);
|
||||
return true;
|
||||
|
||||
case 0xc3:
|
||||
variant.setBoolean(true);
|
||||
if (allowValue)
|
||||
variant.setBoolean(true);
|
||||
return true;
|
||||
|
||||
case 0xcc:
|
||||
return readInteger<uint8_t>(variant);
|
||||
case 0xc4: // bin 8
|
||||
if (allowValue)
|
||||
return notSupported();
|
||||
else
|
||||
return skipString<uint8_t>();
|
||||
|
||||
case 0xcd:
|
||||
return readInteger<uint16_t>(variant);
|
||||
case 0xc5: // bin 16
|
||||
if (allowValue)
|
||||
return notSupported();
|
||||
else
|
||||
return skipString<uint16_t>();
|
||||
|
||||
case 0xce:
|
||||
return readInteger<uint32_t>(variant);
|
||||
case 0xc6: // bin 32
|
||||
if (allowValue)
|
||||
return notSupported();
|
||||
else
|
||||
return skipString<uint32_t>();
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
case 0xcf:
|
||||
return readInteger<uint64_t>(variant);
|
||||
#endif
|
||||
case 0xc7: // ext 8
|
||||
if (allowValue)
|
||||
return notSupported();
|
||||
else
|
||||
return skipExt<uint8_t>();
|
||||
|
||||
case 0xd0:
|
||||
return readInteger<int8_t>(variant);
|
||||
case 0xc8: // ext 16
|
||||
if (allowValue)
|
||||
return notSupported();
|
||||
else
|
||||
return skipExt<uint16_t>();
|
||||
|
||||
case 0xd1:
|
||||
return readInteger<int16_t>(variant);
|
||||
|
||||
case 0xd2:
|
||||
return readInteger<int32_t>(variant);
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
case 0xd3:
|
||||
return readInteger<int64_t>(variant);
|
||||
#endif
|
||||
case 0xc9: // ext 32
|
||||
if (allowValue)
|
||||
return notSupported();
|
||||
else
|
||||
return skipExt<uint32_t>();
|
||||
|
||||
case 0xca:
|
||||
return readFloat<float>(variant);
|
||||
if (allowValue)
|
||||
return readFloat<float>(variant);
|
||||
else
|
||||
return skipBytes(4);
|
||||
|
||||
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:
|
||||
return readString<uint8_t>(variant);
|
||||
if (allowValue)
|
||||
return readString<uint8_t>(variant);
|
||||
else
|
||||
return skipString<uint8_t>();
|
||||
|
||||
case 0xda:
|
||||
return readString<uint16_t>(variant);
|
||||
if (allowValue)
|
||||
return readString<uint16_t>(variant);
|
||||
else
|
||||
return skipString<uint16_t>();
|
||||
|
||||
case 0xdb:
|
||||
return readString<uint32_t>(variant);
|
||||
if (allowValue)
|
||||
return readString<uint32_t>(variant);
|
||||
else
|
||||
return skipString<uint32_t>();
|
||||
|
||||
case 0xdc:
|
||||
return readArray<uint16_t>(variant.toArray(), nestingLimit);
|
||||
return readArray<uint16_t>(variant, filter, nestingLimit);
|
||||
|
||||
case 0xdd:
|
||||
return readArray<uint32_t>(variant.toArray(), nestingLimit);
|
||||
return readArray<uint32_t>(variant, filter, nestingLimit);
|
||||
|
||||
case 0xde:
|
||||
return readObject<uint16_t>(variant.toObject(), nestingLimit);
|
||||
return readObject<uint16_t>(variant, filter, nestingLimit);
|
||||
|
||||
case 0xdf:
|
||||
return readObject<uint32_t>(variant.toObject(), nestingLimit);
|
||||
|
||||
default:
|
||||
_error = DeserializationError::NotSupported;
|
||||
return false;
|
||||
return readObject<uint32_t>(variant, filter, nestingLimit);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Prevent VS warning "assignment operator could not be generated"
|
||||
MsgPackDeserializer &operator=(const MsgPackDeserializer &);
|
||||
switch (code & 0xf0) {
|
||||
case 0x80:
|
||||
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) {
|
||||
int c = _reader.read();
|
||||
@@ -159,6 +282,16 @@ class MsgPackDeserializer {
|
||||
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>
|
||||
bool readInteger(T &value) {
|
||||
if (!readBytes(value))
|
||||
@@ -221,24 +354,31 @@ class MsgPackDeserializer {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool readString(const char *&str) {
|
||||
bool readString() {
|
||||
T size;
|
||||
if (!readInteger(size))
|
||||
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) {
|
||||
const char *s = 0; // <- mute "maybe-uninitialized" (+4 bytes on AVR)
|
||||
if (!readString(s, n))
|
||||
if (!readString(n))
|
||||
return false;
|
||||
variant.setString(make_not_null(s),
|
||||
typename TStringStorage::storage_policy());
|
||||
variant.setStringPointer(_stringStorage.save(),
|
||||
typename TStringStorage::storage_policy());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool readString(const char *&result, size_t n) {
|
||||
_stringStorage.startString(_pool);
|
||||
bool readString(size_t n) {
|
||||
_stringStorage.startString();
|
||||
for (; n; --n) {
|
||||
uint8_t c;
|
||||
if (!readBytes(c))
|
||||
@@ -251,131 +391,247 @@ class MsgPackDeserializer {
|
||||
return false;
|
||||
}
|
||||
|
||||
result = _stringStorage.save(_pool);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TSize>
|
||||
bool readArray(CollectionData &array, NestingLimit nestingLimit) {
|
||||
template <typename TSize, typename TFilter>
|
||||
bool readArray(VariantData &variant, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
TSize size;
|
||||
if (!readInteger(size))
|
||||
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()) {
|
||||
_error = DeserializationError::TooDeep;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool allowArray = filter.allowArray();
|
||||
|
||||
CollectionData *array = allowArray ? &variant.toArray() : 0;
|
||||
|
||||
TFilter memberFilter = filter[0U];
|
||||
|
||||
for (; n; --n) {
|
||||
VariantData *value = array.addElement(_pool);
|
||||
if (!value) {
|
||||
_error = DeserializationError::NoMemory;
|
||||
return false;
|
||||
VariantData *value;
|
||||
|
||||
if (memberFilter.allow()) {
|
||||
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 true;
|
||||
}
|
||||
|
||||
template <typename TSize>
|
||||
bool readObject(CollectionData &object, NestingLimit nestingLimit) {
|
||||
template <typename TSize, typename TFilter>
|
||||
bool readObject(VariantData &variant, TFilter filter,
|
||||
NestingLimit nestingLimit) {
|
||||
TSize size;
|
||||
if (!readInteger(size))
|
||||
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()) {
|
||||
_error = DeserializationError::TooDeep;
|
||||
return false;
|
||||
}
|
||||
|
||||
CollectionData *object = filter.allowObject() ? &variant.toObject() : 0;
|
||||
|
||||
for (; n; --n) {
|
||||
VariantSlot *slot = object.addSlot(_pool);
|
||||
if (!slot) {
|
||||
_error = DeserializationError::NoMemory;
|
||||
if (!readKey())
|
||||
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 (!parseKey(key))
|
||||
return false;
|
||||
|
||||
slot->setKey(key, typename TStringStorage::storage_policy());
|
||||
|
||||
if (!parseVariant(*slot->data(), nestingLimit.decrement()))
|
||||
if (!parseVariant(*member, memberFilter, nestingLimit.decrement()))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parseKey(const char *&key) {
|
||||
bool readKey() {
|
||||
uint8_t code;
|
||||
if (!readByte(code))
|
||||
return false;
|
||||
|
||||
if ((code & 0xe0) == 0xa0)
|
||||
return readString(key, code & 0x1f);
|
||||
return readString(code & 0x1f);
|
||||
|
||||
switch (code) {
|
||||
case 0xd9:
|
||||
return readString<uint8_t>(key);
|
||||
return readString<uint8_t>();
|
||||
|
||||
case 0xda:
|
||||
return readString<uint16_t>(key);
|
||||
return readString<uint16_t>();
|
||||
|
||||
case 0xdb:
|
||||
return readString<uint32_t>(key);
|
||||
return readString<uint32_t>();
|
||||
|
||||
default:
|
||||
_error = DeserializationError::NotSupported;
|
||||
return false;
|
||||
return notSupported();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool skipExt() {
|
||||
T size;
|
||||
if (!readInteger(size))
|
||||
return false;
|
||||
return skipBytes(size + 1);
|
||||
}
|
||||
|
||||
MemoryPool *_pool;
|
||||
TReader _reader;
|
||||
TStringStorage _stringStorage;
|
||||
DeserializationError _error;
|
||||
bool _foundSomething;
|
||||
};
|
||||
|
||||
template <typename TInput>
|
||||
//
|
||||
// deserializeMsgPack(JsonDocument&, const std::string&, ...)
|
||||
//
|
||||
// ... = NestingLimit
|
||||
template <typename TString>
|
||||
DeserializationError deserializeMsgPack(
|
||||
JsonDocument &doc, const TInput &input,
|
||||
JsonDocument &doc, const TString &input,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
|
||||
AllowAllFilter());
|
||||
}
|
||||
|
||||
template <typename TInput>
|
||||
// ... = Filter, NestingLimit
|
||||
template <typename TString>
|
||||
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()) {
|
||||
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
|
||||
AllowAllFilter());
|
||||
}
|
||||
|
||||
template <typename TInput>
|
||||
// ... = Filter, NestingLimit
|
||||
template <typename TStream>
|
||||
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()) {
|
||||
return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit,
|
||||
AllowAllFilter());
|
||||
}
|
||||
|
||||
template <typename TInput>
|
||||
// ... = Filter, NestingLimit
|
||||
template <typename TChar>
|
||||
DeserializationError deserializeMsgPack(
|
||||
JsonDocument &doc, TInput &input,
|
||||
JsonDocument &doc, TChar *input, size_t inputSize, Filter filter,
|
||||
NestingLimit nestingLimit = NestingLimit()) {
|
||||
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
|
||||
AllowAllFilter());
|
||||
return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit,
|
||||
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
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <ArduinoJson/MsgPack/endianess.hpp>
|
||||
#include <ArduinoJson/Polyfills/assert.hpp>
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
#include <ArduinoJson/Serialization/CountingDecorator.hpp>
|
||||
#include <ArduinoJson/Serialization/measure.hpp>
|
||||
#include <ArduinoJson/Serialization/serialize.hpp>
|
||||
#include <ArduinoJson/Variant/VariantData.hpp>
|
||||
@@ -14,19 +15,20 @@
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TWriter>
|
||||
class MsgPackSerializer {
|
||||
class MsgPackSerializer : public Visitor<size_t> {
|
||||
public:
|
||||
MsgPackSerializer(TWriter writer) : _writer(writer), _bytesWritten(0) {}
|
||||
MsgPackSerializer(TWriter writer) : _writer(writer) {}
|
||||
|
||||
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);
|
||||
writeInteger(value32);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
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);
|
||||
if (value32 == value64) {
|
||||
writeByte(0xCA);
|
||||
@@ -35,9 +37,10 @@ class MsgPackSerializer {
|
||||
writeByte(0xCB);
|
||||
writeInteger(value64);
|
||||
}
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
void visitArray(const CollectionData& array) {
|
||||
size_t visitArray(const CollectionData& array) {
|
||||
size_t n = array.size();
|
||||
if (n < 0x10) {
|
||||
writeByte(uint8_t(0x90 + array.size()));
|
||||
@@ -51,9 +54,10 @@ class MsgPackSerializer {
|
||||
for (VariantSlot* slot = array.head(); slot; slot = slot->next()) {
|
||||
slot->data()->accept(*this);
|
||||
}
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
void visitObject(const CollectionData& object) {
|
||||
size_t visitObject(const CollectionData& object) {
|
||||
size_t n = object.size();
|
||||
if (n < 0x10) {
|
||||
writeByte(uint8_t(0x80 + n));
|
||||
@@ -68,9 +72,10 @@ class MsgPackSerializer {
|
||||
visitString(slot->key());
|
||||
slot->data()->accept(*this);
|
||||
}
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
void visitString(const char* value) {
|
||||
size_t visitString(const char* value) {
|
||||
ARDUINOJSON_ASSERT(value != NULL);
|
||||
|
||||
size_t n = strlen(value);
|
||||
@@ -88,13 +93,15 @@ class MsgPackSerializer {
|
||||
writeInteger(uint32_t(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);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
void visitNegativeInteger(UInt value) {
|
||||
size_t visitNegativeInteger(UInt value) {
|
||||
UInt negated = UInt(~value + 1);
|
||||
if (value <= 0x20) {
|
||||
writeInteger(int8_t(negated));
|
||||
@@ -114,9 +121,10 @@ class MsgPackSerializer {
|
||||
writeInteger(int64_t(negated));
|
||||
}
|
||||
#endif
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
void visitPositiveInteger(UInt value) {
|
||||
size_t visitPositiveInteger(UInt value) {
|
||||
if (value <= 0x7F) {
|
||||
writeInteger(uint8_t(value));
|
||||
} else if (value <= 0xFF) {
|
||||
@@ -141,27 +149,30 @@ class MsgPackSerializer {
|
||||
writeInteger(uint64_t(value));
|
||||
}
|
||||
#endif
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
void visitBoolean(bool value) {
|
||||
size_t visitBoolean(bool value) {
|
||||
writeByte(value ? 0xC3 : 0xC2);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
void visitNull() {
|
||||
size_t visitNull() {
|
||||
writeByte(0xC0);
|
||||
}
|
||||
|
||||
size_t bytesWritten() const {
|
||||
return _bytesWritten;
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
private:
|
||||
size_t bytesWritten() const {
|
||||
return _writer.count();
|
||||
}
|
||||
|
||||
void writeByte(uint8_t c) {
|
||||
_bytesWritten += _writer.write(c);
|
||||
_writer.write(c);
|
||||
}
|
||||
|
||||
void writeBytes(const uint8_t* p, size_t n) {
|
||||
_bytesWritten += _writer.write(p, n);
|
||||
_writer.write(p, n);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -170,8 +181,7 @@ class MsgPackSerializer {
|
||||
writeBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
|
||||
}
|
||||
|
||||
TWriter _writer;
|
||||
size_t _bytesWritten;
|
||||
CountingDecorator<TWriter> _writer;
|
||||
};
|
||||
|
||||
template <typename TSource, typename TDestination>
|
||||
|
||||
@@ -5,45 +5,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Configuration.hpp>
|
||||
#include <ArduinoJson/Polyfills/preprocessor.hpp>
|
||||
#include <ArduinoJson/version.hpp>
|
||||
|
||||
#ifndef ARDUINOJSON_NAMESPACE
|
||||
|
||||
#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)
|
||||
|
||||
#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, \
|
||||
#define ARDUINOJSON_NAMESPACE \
|
||||
ARDUINOJSON_CONCAT4( \
|
||||
ARDUINOJSON_CONCAT4(ArduinoJson, ARDUINOJSON_VERSION_MAJOR, \
|
||||
ARDUINOJSON_VERSION_MINOR, \
|
||||
ARDUINOJSON_VERSION_REVISION), \
|
||||
_, \
|
||||
ARDUINOJSON_HEX_DIGIT(ARDUINOJSON_ENABLE_PROGMEM, \
|
||||
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))
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <ArduinoJson/Configuration.hpp>
|
||||
#include <ArduinoJson/Polyfills/alias_cast.hpp>
|
||||
#include <ArduinoJson/Polyfills/math.hpp>
|
||||
#include <ArduinoJson/Polyfills/preprocessor.hpp>
|
||||
#include <ArduinoJson/Polyfills/static_array.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
@@ -46,48 +48,60 @@ struct FloatTraits<T, 8 /*64bits*/> {
|
||||
}
|
||||
|
||||
static T positiveBinaryPowerOfTen(int index) {
|
||||
static T factors[] = {
|
||||
1e1,
|
||||
1e2,
|
||||
1e4,
|
||||
1e8,
|
||||
1e16,
|
||||
forge(0x4693B8B5, 0xB5056E17), // 1e32
|
||||
forge(0x4D384F03, 0xE93FF9F5), // 1e64
|
||||
forge(0x5A827748, 0xF9301D32), // 1e128
|
||||
forge(0x75154FDD, 0x7F73BF3C) // 1e256
|
||||
};
|
||||
return factors[index];
|
||||
ARDUINOJSON_DEFINE_STATIC_ARRAY( //
|
||||
uint32_t, factors,
|
||||
ARDUINOJSON_EXPAND18({
|
||||
0x40240000, 0x00000000, // 1e1
|
||||
0x40590000, 0x00000000, // 1e2
|
||||
0x40C38800, 0x00000000, // 1e4
|
||||
0x4197D784, 0x00000000, // 1e8
|
||||
0x4341C379, 0x37E08000, // 1e16
|
||||
0x4693B8B5, 0xB5056E17, // 1e32
|
||||
0x4D384F03, 0xE93FF9F5, // 1e64
|
||||
0x5A827748, 0xF9301D32, // 1e128
|
||||
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 factors[] = {
|
||||
forge(0x3FB99999, 0x9999999A), // 1e-1
|
||||
forge(0x3F847AE1, 0x47AE147B), // 1e-2
|
||||
forge(0x3F1A36E2, 0xEB1C432D), // 1e-4
|
||||
forge(0x3E45798E, 0xE2308C3A), // 1e-8
|
||||
forge(0x3C9CD2B2, 0x97D889BC), // 1e-16
|
||||
forge(0x3949F623, 0xD5A8A733), // 1e-32
|
||||
forge(0x32A50FFD, 0x44F4A73D), // 1e-64
|
||||
forge(0x255BBA08, 0xCF8C979D), // 1e-128
|
||||
forge(0x0AC80628, 0x64AC6F43) // 1e-256
|
||||
};
|
||||
return factors[index];
|
||||
ARDUINOJSON_DEFINE_STATIC_ARRAY( //
|
||||
uint32_t, factors,
|
||||
ARDUINOJSON_EXPAND18({
|
||||
0x3FB99999, 0x9999999A, // 1e-1
|
||||
0x3F847AE1, 0x47AE147B, // 1e-2
|
||||
0x3F1A36E2, 0xEB1C432D, // 1e-4
|
||||
0x3E45798E, 0xE2308C3A, // 1e-8
|
||||
0x3C9CD2B2, 0x97D889BC, // 1e-16
|
||||
0x3949F623, 0xD5A8A733, // 1e-32
|
||||
0x32A50FFD, 0x44F4A73D, // 1e-64
|
||||
0x255BBA08, 0xCF8C979D, // 1e-128
|
||||
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 factors[] = {
|
||||
1e0,
|
||||
forge(0x3FB99999, 0x9999999A), // 1e-1
|
||||
forge(0x3F50624D, 0xD2F1A9FC), // 1e-3
|
||||
forge(0x3E7AD7F2, 0x9ABCAF48), // 1e-7
|
||||
forge(0x3CD203AF, 0x9EE75616), // 1e-15
|
||||
forge(0x398039D6, 0x65896880), // 1e-31
|
||||
forge(0x32DA53FC, 0x9631D10D), // 1e-63
|
||||
forge(0x25915445, 0x81B7DEC2), // 1e-127
|
||||
forge(0x0AFE07B2, 0x7DD78B14) // 1e-255
|
||||
};
|
||||
return factors[index];
|
||||
ARDUINOJSON_DEFINE_STATIC_ARRAY( //
|
||||
uint32_t, factors,
|
||||
ARDUINOJSON_EXPAND18({
|
||||
0x3FF00000, 0x00000000, // 1e0
|
||||
0x3FB99999, 0x9999999A, // 1e-1
|
||||
0x3F50624D, 0xD2F1A9FC, // 1e-3
|
||||
0x3E7AD7F2, 0x9ABCAF48, // 1e-7
|
||||
0x3CD203AF, 0x9EE75616, // 1e-15
|
||||
0x398039D6, 0x65896880, // 1e-31
|
||||
0x32DA53FC, 0x9631D10D, // 1e-63
|
||||
0x25915445, 0x81B7DEC2, // 1e-127
|
||||
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() {
|
||||
@@ -144,18 +158,24 @@ struct FloatTraits<T, 4 /*32bits*/> {
|
||||
}
|
||||
|
||||
static T positiveBinaryPowerOfTen(int index) {
|
||||
static T factors[] = {1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f};
|
||||
return factors[index];
|
||||
ARDUINOJSON_DEFINE_STATIC_ARRAY(
|
||||
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 factors[] = {1e-1f, 1e-2f, 1e-4f, 1e-8f, 1e-16f, 1e-32f};
|
||||
return factors[index];
|
||||
ARDUINOJSON_DEFINE_STATIC_ARRAY(
|
||||
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 factors[] = {1e0f, 1e-1f, 1e-3f, 1e-7f, 1e-15f, 1e-31f};
|
||||
return factors[index];
|
||||
ARDUINOJSON_DEFINE_STATIC_ARRAY(
|
||||
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) {
|
||||
|
||||
@@ -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/math.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 {
|
||||
|
||||
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>
|
||||
struct choose_largest : conditional<(sizeof(A) > sizeof(B)), A, B> {};
|
||||
|
||||
template <typename TFloat, typename TUInt>
|
||||
inline void parseNumber(const char* s, ParsedNumber<TFloat, TUInt>& result) {
|
||||
typedef FloatTraits<TFloat> traits;
|
||||
typedef typename choose_largest<typename traits::mantissa_type, TUInt>::type
|
||||
mantissa_t;
|
||||
typedef typename traits::exponent_type exponent_t;
|
||||
inline bool parseNumber(const char* s, VariantData& result) {
|
||||
typedef FloatTraits<Float> traits;
|
||||
typedef choose_largest<traits::mantissa_type, UInt>::type mantissa_t;
|
||||
typedef traits::exponent_type exponent_t;
|
||||
|
||||
ARDUINOJSON_ASSERT(s != 0);
|
||||
|
||||
@@ -80,24 +39,23 @@ inline void parseNumber(const char* s, ParsedNumber<TFloat, TUInt>& result) {
|
||||
#if ARDUINOJSON_ENABLE_NAN
|
||||
if (*s == 'n' || *s == 'N') {
|
||||
result.setFloat(traits::nan());
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_ENABLE_INFINITY
|
||||
if (*s == 'i' || *s == 'I') {
|
||||
result.setFloat(is_negative ? -traits::inf() : traits::inf());
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!isdigit(*s) && *s != '.')
|
||||
return;
|
||||
return false;
|
||||
|
||||
mantissa_t mantissa = 0;
|
||||
exponent_t exponent_offset = 0;
|
||||
const mantissa_t maxUint = TUInt(-1);
|
||||
const mantissa_t maxUint = UInt(-1);
|
||||
|
||||
while (isdigit(*s)) {
|
||||
uint8_t digit = uint8_t(*s - '0');
|
||||
@@ -111,8 +69,11 @@ inline void parseNumber(const char* s, ParsedNumber<TFloat, TUInt>& result) {
|
||||
}
|
||||
|
||||
if (*s == '\0') {
|
||||
result.setInteger(TUInt(mantissa), is_negative);
|
||||
return;
|
||||
if (is_negative)
|
||||
result.setNegativeInteger(UInt(mantissa));
|
||||
else
|
||||
result.setPositiveInteger(UInt(mantissa));
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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);
|
||||
else
|
||||
result.setFloat(is_negative ? -traits::inf() : traits::inf());
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
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
|
||||
if (*s != '\0')
|
||||
return;
|
||||
return false;
|
||||
|
||||
TFloat final_result =
|
||||
traits::make_float(static_cast<TFloat>(mantissa), exponent);
|
||||
Float final_result =
|
||||
traits::make_float(static_cast<Float>(mantissa), exponent);
|
||||
|
||||
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
|
||||
|
||||
@@ -120,8 +120,8 @@ class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >,
|
||||
return getOrAddUpstreamMember().set(value);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void accept(Visitor &visitor) const {
|
||||
template <typename TVisitor>
|
||||
typename TVisitor::result_type accept(TVisitor &visitor) const {
|
||||
return getUpstreamMember().accept(visitor);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,12 +8,13 @@
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename Visitor>
|
||||
void objectAccept(const CollectionData *obj, Visitor &visitor) {
|
||||
template <typename TVisitor>
|
||||
typename TVisitor::result_type objectAccept(const CollectionData *obj,
|
||||
TVisitor &visitor) {
|
||||
if (obj)
|
||||
visitor.visitObject(*obj);
|
||||
return visitor.visitObject(*obj);
|
||||
else
|
||||
visitor.visitNull();
|
||||
return visitor.visitNull();
|
||||
}
|
||||
|
||||
inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) {
|
||||
|
||||
@@ -22,9 +22,9 @@ class ObjectRefBase {
|
||||
return VariantConstRef(reinterpret_cast<const VariantData*>(data));
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
FORCE_INLINE void accept(Visitor& visitor) const {
|
||||
objectAccept(_data, visitor);
|
||||
template <typename TVisitor>
|
||||
typename TVisitor::result_type accept(TVisitor& visitor) const {
|
||||
return objectAccept(_data, visitor);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
#include <ArduinoJson/Configuration.hpp>
|
||||
#include <ArduinoJson/Namespace.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_floating_point.hpp"
|
||||
#include "type_traits/is_integral.hpp"
|
||||
#include "type_traits/is_pointer.hpp"
|
||||
#include "type_traits/is_same.hpp"
|
||||
#include "type_traits/is_signed.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
|
||||
|
||||
#include <WString.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
|
||||
@@ -12,8 +12,7 @@ template <template <typename> class TSerializer, typename TSource>
|
||||
size_t measure(const TSource &source) {
|
||||
DummyWriter dp;
|
||||
TSerializer<DummyWriter> serializer(dp);
|
||||
source.accept(serializer);
|
||||
return serializer.bytesWritten();
|
||||
return source.accept(serializer);
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -12,8 +12,7 @@ template <template <typename> class TSerializer, typename TSource,
|
||||
typename TWriter>
|
||||
size_t doSerialize(const TSource &source, TWriter writer) {
|
||||
TSerializer<TWriter> serializer(writer);
|
||||
source.accept(serializer);
|
||||
return serializer.bytesWritten();
|
||||
return source.accept(serializer);
|
||||
}
|
||||
|
||||
template <template <typename> class TSerializer, typename TSource,
|
||||
|
||||
@@ -10,14 +10,16 @@ namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class StringCopier {
|
||||
public:
|
||||
void startString(MemoryPool* pool) {
|
||||
pool->getFreeZone(&_ptr, &_capacity);
|
||||
StringCopier(MemoryPool& pool) : _pool(&pool) {}
|
||||
|
||||
void startString() {
|
||||
_pool->getFreeZone(&_ptr, &_capacity);
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
const char* save(MemoryPool* pool) {
|
||||
const char* save() {
|
||||
ARDUINOJSON_ASSERT(_ptr);
|
||||
return pool->saveStringFromFreeZone(_size);
|
||||
return _pool->saveStringFromFreeZone(_size);
|
||||
}
|
||||
|
||||
void append(const char* s) {
|
||||
@@ -34,6 +36,7 @@ class StringCopier {
|
||||
|
||||
if (_size >= _capacity) {
|
||||
_ptr = 0;
|
||||
_pool->markAsOverflowed();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -51,6 +54,7 @@ class StringCopier {
|
||||
typedef storage_policies::store_by_copy storage_policy;
|
||||
|
||||
private:
|
||||
MemoryPool* _pool;
|
||||
char* _ptr;
|
||||
size_t _size;
|
||||
size_t _capacity;
|
||||
|
||||
@@ -13,11 +13,11 @@ class StringMover {
|
||||
public:
|
||||
StringMover(char* ptr) : _writePtr(ptr) {}
|
||||
|
||||
void startString(MemoryPool*) {
|
||||
void startString() {
|
||||
_startPtr = _writePtr;
|
||||
}
|
||||
|
||||
const char* save(MemoryPool*) const {
|
||||
const char* save() const {
|
||||
return _startPtr;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,32 +9,15 @@
|
||||
|
||||
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>
|
||||
typename StringStorage<TInput>::type makeStringStorage(TInput& input) {
|
||||
return StringStorage<TInput>::create(input);
|
||||
StringCopier makeStringStorage(TInput&, MemoryPool& pool) {
|
||||
return StringCopier(pool);
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
typename StringStorage<TChar*>::type makeStringStorage(TChar* input) {
|
||||
return StringStorage<TChar*>::create(input);
|
||||
StringMover makeStringStorage(
|
||||
TChar* input, MemoryPool&,
|
||||
typename enable_if<!is_const<TChar>::value>::type* = 0) {
|
||||
return StringMover(reinterpret_cast<char*>(input));
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <WString.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
#include <ArduinoJson/Polyfills/safe_strcmp.hpp>
|
||||
#include <ArduinoJson/Strings/IsString.hpp>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
|
||||
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
#include <WString.h>
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STRING
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TString>
|
||||
class StlStringAdapter {
|
||||
class StdStringAdapter {
|
||||
public:
|
||||
StlStringAdapter(const TString& str) : _str(&str) {}
|
||||
StdStringAdapter(const TString& str) : _str(&str) {}
|
||||
|
||||
void copyTo(char* p, size_t n) const {
|
||||
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>
|
||||
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) {
|
||||
return StlStringAdapter<std::basic_string<char, TCharTraits, TAllocator> >(
|
||||
return StdStringAdapter<std::basic_string<char, TCharTraits, TAllocator> >(
|
||||
str);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <ArduinoJson/Strings/SizedRamStringAdapter.hpp>
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STRING
|
||||
#include <ArduinoJson/Strings/StlStringAdapter.hpp>
|
||||
#include <ArduinoJson/Strings/StdStringAdapter.hpp>
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
|
||||
@@ -14,20 +14,34 @@ namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class CollectionData;
|
||||
|
||||
struct ComparerBase {
|
||||
CompareResult result;
|
||||
|
||||
ComparerBase() : result(COMPARE_RESULT_DIFFER) {}
|
||||
|
||||
void visitArray(const CollectionData &) {}
|
||||
void visitBoolean(bool) {}
|
||||
void visitFloat(Float) {}
|
||||
void visitNegativeInteger(UInt) {}
|
||||
void visitNull() {}
|
||||
void visitObject(const CollectionData &) {}
|
||||
void visitPositiveInteger(UInt) {}
|
||||
void visitRawJson(const char *, size_t) {}
|
||||
void visitString(const char *) {}
|
||||
struct ComparerBase : Visitor<CompareResult> {
|
||||
CompareResult visitArray(const CollectionData &) {
|
||||
return COMPARE_RESULT_DIFFER;
|
||||
}
|
||||
CompareResult visitBoolean(bool) {
|
||||
return COMPARE_RESULT_DIFFER;
|
||||
}
|
||||
CompareResult visitFloat(Float) {
|
||||
return COMPARE_RESULT_DIFFER;
|
||||
}
|
||||
CompareResult visitNegativeInteger(UInt) {
|
||||
return COMPARE_RESULT_DIFFER;
|
||||
}
|
||||
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>
|
||||
@@ -40,19 +54,21 @@ struct Comparer<T, typename enable_if<IsString<T>::value>::type>
|
||||
|
||||
explicit Comparer(T value) : rhs(value) {}
|
||||
|
||||
void visitString(const char *lhs) {
|
||||
CompareResult visitString(const char *lhs) {
|
||||
int i = adaptString(rhs).compare(lhs);
|
||||
if (i < 0)
|
||||
result = COMPARE_RESULT_GREATER;
|
||||
return COMPARE_RESULT_GREATER;
|
||||
else if (i > 0)
|
||||
result = COMPARE_RESULT_LESS;
|
||||
return COMPARE_RESULT_LESS;
|
||||
else
|
||||
result = COMPARE_RESULT_EQUAL;
|
||||
return COMPARE_RESULT_EQUAL;
|
||||
}
|
||||
|
||||
void visitNull() {
|
||||
CompareResult visitNull() {
|
||||
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) {}
|
||||
|
||||
void visitFloat(Float lhs) {
|
||||
result = arithmeticCompare(lhs, rhs);
|
||||
CompareResult visitFloat(Float lhs) {
|
||||
return arithmeticCompare(lhs, rhs);
|
||||
}
|
||||
|
||||
void visitNegativeInteger(UInt lhs) {
|
||||
result = arithmeticCompareNegateLeft(lhs, rhs);
|
||||
CompareResult visitNegativeInteger(UInt lhs) {
|
||||
return arithmeticCompareNegateLeft(lhs, rhs);
|
||||
}
|
||||
|
||||
void visitPositiveInteger(UInt lhs) {
|
||||
result = arithmeticCompare(lhs, rhs);
|
||||
CompareResult visitPositiveInteger(UInt lhs) {
|
||||
return arithmeticCompare(lhs, rhs);
|
||||
}
|
||||
|
||||
void visitBoolean(bool lhs) {
|
||||
visitPositiveInteger(static_cast<UInt>(lhs));
|
||||
CompareResult visitBoolean(bool lhs) {
|
||||
return visitPositiveInteger(static_cast<UInt>(lhs));
|
||||
}
|
||||
};
|
||||
|
||||
struct NullComparer : ComparerBase {
|
||||
void visitNull() {
|
||||
result = COMPARE_RESULT_EQUAL;
|
||||
CompareResult visitNull() {
|
||||
return COMPARE_RESULT_EQUAL;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -99,9 +115,11 @@ struct ArrayComparer : ComparerBase {
|
||||
|
||||
explicit ArrayComparer(const CollectionData &rhs) : _rhs(&rhs) {}
|
||||
|
||||
void visitArray(const CollectionData &lhs) {
|
||||
CompareResult visitArray(const CollectionData &lhs) {
|
||||
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) {}
|
||||
|
||||
void visitFloat(Float lhs) {
|
||||
result = arithmeticCompareNegateRight(lhs, _rhs);
|
||||
CompareResult visitFloat(Float lhs) {
|
||||
return arithmeticCompareNegateRight(lhs, _rhs);
|
||||
}
|
||||
|
||||
void visitNegativeInteger(UInt lhs) {
|
||||
result = arithmeticCompare(_rhs, lhs);
|
||||
CompareResult visitNegativeInteger(UInt lhs) {
|
||||
return arithmeticCompare(_rhs, lhs);
|
||||
}
|
||||
|
||||
void visitPositiveInteger(UInt) {
|
||||
result = COMPARE_RESULT_GREATER;
|
||||
CompareResult visitPositiveInteger(UInt) {
|
||||
return COMPARE_RESULT_GREATER;
|
||||
}
|
||||
|
||||
void visitBoolean(bool) {
|
||||
result = COMPARE_RESULT_GREATER;
|
||||
CompareResult visitBoolean(bool) {
|
||||
return COMPARE_RESULT_GREATER;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -132,9 +150,11 @@ struct ObjectComparer : ComparerBase {
|
||||
|
||||
explicit ObjectComparer(const CollectionData &rhs) : _rhs(&rhs) {}
|
||||
|
||||
void visitObject(const CollectionData &lhs) {
|
||||
CompareResult visitObject(const CollectionData &lhs) {
|
||||
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)
|
||||
: _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;
|
||||
int n = memcmp(lhsData, _rhsData, size);
|
||||
if (n < 0)
|
||||
result = COMPARE_RESULT_LESS;
|
||||
return COMPARE_RESULT_LESS;
|
||||
else if (n > 0)
|
||||
result = COMPARE_RESULT_GREATER;
|
||||
return COMPARE_RESULT_GREATER;
|
||||
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) {}
|
||||
|
||||
void visitArray(const CollectionData &lhs) {
|
||||
CompareResult visitArray(const CollectionData &lhs) {
|
||||
ArrayComparer comparer(lhs);
|
||||
accept(comparer);
|
||||
return accept(comparer);
|
||||
}
|
||||
|
||||
void visitObject(const CollectionData &lhs) {
|
||||
CompareResult visitObject(const CollectionData &lhs) {
|
||||
ObjectComparer comparer(lhs);
|
||||
accept(comparer);
|
||||
return accept(comparer);
|
||||
}
|
||||
|
||||
void visitFloat(Float lhs) {
|
||||
CompareResult visitFloat(Float 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);
|
||||
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);
|
||||
accept(comparer);
|
||||
return accept(comparer);
|
||||
}
|
||||
|
||||
void visitNegativeInteger(UInt lhs) {
|
||||
CompareResult visitNegativeInteger(UInt lhs) {
|
||||
NegativeIntegerComparer comparer(lhs);
|
||||
accept(comparer);
|
||||
return accept(comparer);
|
||||
}
|
||||
|
||||
void visitPositiveInteger(UInt lhs) {
|
||||
CompareResult visitPositiveInteger(UInt lhs) {
|
||||
Comparer<UInt> comparer(lhs);
|
||||
accept(comparer);
|
||||
return accept(comparer);
|
||||
}
|
||||
|
||||
void visitBoolean(bool lhs) {
|
||||
CompareResult visitBoolean(bool lhs) {
|
||||
Comparer<bool> comparer(lhs);
|
||||
accept(comparer);
|
||||
return accept(comparer);
|
||||
}
|
||||
|
||||
void visitNull() {
|
||||
CompareResult visitNull() {
|
||||
NullComparer comparer;
|
||||
accept(comparer);
|
||||
return accept(comparer);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename TComparer>
|
||||
void accept(TComparer &comparer) {
|
||||
rhs.accept(comparer);
|
||||
switch (comparer.result) {
|
||||
CompareResult accept(TComparer &comparer) {
|
||||
CompareResult reversedResult = rhs.accept(comparer);
|
||||
switch (reversedResult) {
|
||||
case COMPARE_RESULT_GREATER:
|
||||
result = COMPARE_RESULT_LESS;
|
||||
break;
|
||||
return COMPARE_RESULT_LESS;
|
||||
case COMPARE_RESULT_LESS:
|
||||
result = COMPARE_RESULT_GREATER;
|
||||
break;
|
||||
return COMPARE_RESULT_GREATER;
|
||||
default:
|
||||
result = comparer.result;
|
||||
break;
|
||||
return reversedResult;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -230,8 +247,7 @@ struct Comparer<T, typename enable_if<IsVisitable<T>::value>::type>
|
||||
template <typename T1, typename T2>
|
||||
CompareResult compare(const T1 &lhs, const T2 &rhs) {
|
||||
Comparer<T2> comparer(rhs);
|
||||
lhs.accept(comparer);
|
||||
return comparer.result;
|
||||
return lhs.accept(comparer);
|
||||
}
|
||||
|
||||
inline int variantCompare(const VariantData *a, const VariantData *b) {
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <ArduinoJson/Memory/MemoryPool.hpp>
|
||||
#include <ArduinoJson/Misc/SerializedValue.hpp>
|
||||
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
||||
#include <ArduinoJson/Polyfills/gsl/not_null.hpp>
|
||||
#include <ArduinoJson/Strings/RamStringAdapter.hpp>
|
||||
#include <ArduinoJson/Variant/VariantContent.hpp>
|
||||
|
||||
@@ -33,9 +32,12 @@ class VariantData {
|
||||
// - no destructor
|
||||
// - no virtual
|
||||
// - no inheritance
|
||||
void init() {
|
||||
_flags = 0;
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void accept(Visitor &visitor) const {
|
||||
template <typename TVisitor>
|
||||
typename TVisitor::result_type accept(TVisitor &visitor) const {
|
||||
switch (type()) {
|
||||
case VALUE_IS_FLOAT:
|
||||
return visitor.visitFloat(_content.asFloat);
|
||||
@@ -242,25 +244,14 @@ class VariantData {
|
||||
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);
|
||||
_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);
|
||||
_content.asString = s.get();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
_content.asString = s;
|
||||
}
|
||||
|
||||
template <typename TAdaptedString>
|
||||
@@ -280,14 +271,27 @@ class VariantData {
|
||||
template <typename TAdaptedString>
|
||||
inline bool setString(TAdaptedString value, MemoryPool *,
|
||||
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>
|
||||
inline bool setString(TAdaptedString value, MemoryPool *pool,
|
||||
storage_policies::store_by_copy) {
|
||||
return setString(pool->saveString(value),
|
||||
storage_policies::store_by_copy());
|
||||
if (value.isNull()) {
|
||||
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() {
|
||||
@@ -365,11 +369,11 @@ class VariantData {
|
||||
_content.asCollection.movePointers(stringDistance, variantDistance);
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t type() const {
|
||||
return _flags & VALUE_MASK;
|
||||
}
|
||||
|
||||
private:
|
||||
void setType(uint8_t t) {
|
||||
_flags &= KEY_IS_OWNED;
|
||||
_flags |= t;
|
||||
|
||||
@@ -9,12 +9,13 @@
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename Visitor>
|
||||
inline void variantAccept(const VariantData *var, Visitor &visitor) {
|
||||
template <typename TVisitor>
|
||||
inline typename TVisitor::result_type variantAccept(const VariantData *var,
|
||||
TVisitor &visitor) {
|
||||
if (var != 0)
|
||||
var->accept(visitor);
|
||||
return var->accept(visitor);
|
||||
else
|
||||
visitor.visitNull();
|
||||
return visitor.visitNull();
|
||||
}
|
||||
|
||||
inline const CollectionData *variantAsArray(const VariantData *var) {
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Array/ArrayRef.hpp>
|
||||
#include <ArduinoJson/Configuration.hpp>
|
||||
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
||||
#include <ArduinoJson/Numbers/parseFloat.hpp>
|
||||
#include <ArduinoJson/Numbers/parseInteger.hpp>
|
||||
#include <ArduinoJson/Numbers/parseNumber.hpp>
|
||||
#include <ArduinoJson/Object/ObjectRef.hpp>
|
||||
#include <ArduinoJson/Variant/VariantRef.hpp>
|
||||
|
||||
#include <string.h> // for strcmp
|
||||
@@ -24,7 +25,7 @@ inline T VariantData::asIntegral() const {
|
||||
return convertNegativeInteger<T>(_content.asInteger);
|
||||
case VALUE_IS_LINKED_STRING:
|
||||
case VALUE_IS_OWNED_STRING:
|
||||
return parseInteger<T>(_content.asString);
|
||||
return parseNumber<T>(_content.asString);
|
||||
case VALUE_IS_FLOAT:
|
||||
return convertFloat<T>(_content.asFloat);
|
||||
default:
|
||||
@@ -58,7 +59,7 @@ inline T VariantData::asFloat() const {
|
||||
return -static_cast<T>(_content.asInteger);
|
||||
case VALUE_IS_LINKED_STRING:
|
||||
case VALUE_IS_OWNED_STRING:
|
||||
return parseFloat<T>(_content.asString);
|
||||
return parseNumber<T>(_content.asString);
|
||||
case VALUE_IS_FLOAT:
|
||||
return static_cast<T>(_content.asFloat);
|
||||
default:
|
||||
@@ -138,4 +139,9 @@ template <typename TString>
|
||||
inline VariantRef VariantRef::getOrAddMember(const TString &key) const {
|
||||
return VariantRef(_pool, variantGetOrAddMember(_data, key, _pool));
|
||||
}
|
||||
|
||||
inline VariantConstRef operator|(VariantConstRef preferedValue,
|
||||
VariantConstRef defaultValue) {
|
||||
return preferedValue ? preferedValue : defaultValue;
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
@@ -19,7 +19,8 @@ template <typename TVariant>
|
||||
struct VariantOperators {
|
||||
// Returns the default value if the VariantRef is undefined of incompatible
|
||||
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>())
|
||||
return variant.template as<T>();
|
||||
else
|
||||
@@ -28,8 +29,9 @@ struct VariantOperators {
|
||||
|
||||
// Returns the default value if the VariantRef is undefined of incompatible
|
||||
// Special case for string: null is treated as undefined
|
||||
friend const char *operator|(const TVariant &variant,
|
||||
const char *defaultValue) {
|
||||
template <typename T>
|
||||
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 *>();
|
||||
return value ? value : defaultValue;
|
||||
}
|
||||
|
||||
@@ -261,9 +261,9 @@ class VariantRef : public VariantRefBase<VariantData>,
|
||||
return variantAs<T>(_data, _pool);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
void accept(Visitor &visitor) const {
|
||||
variantAccept(_data, visitor);
|
||||
template <typename TVisitor>
|
||||
typename TVisitor::result_type accept(TVisitor &visitor) const {
|
||||
return variantAccept(_data, visitor);
|
||||
}
|
||||
|
||||
// Change the type of the variant
|
||||
@@ -347,9 +347,9 @@ class VariantConstRef : public VariantRefBase<const VariantData>,
|
||||
VariantConstRef(const VariantData *data) : base_type(data) {}
|
||||
VariantConstRef(VariantRef var) : base_type(var._data) {}
|
||||
|
||||
template <typename Visitor>
|
||||
void accept(Visitor &visitor) const {
|
||||
variantAccept(_data, visitor);
|
||||
template <typename TVisitor>
|
||||
typename TVisitor::result_type accept(TVisitor &visitor) const {
|
||||
return variantAccept(_data, visitor);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
#include <stdint.h> // int8_t, int16_t
|
||||
|
||||
#include <ArduinoJson/Polyfills/gsl/not_null.hpp>
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
#include <ArduinoJson/Strings/StoragePolicy.hpp>
|
||||
#include <ArduinoJson/Variant/VariantContent.hpp>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define ARDUINOJSON_VERSION "6.16.1"
|
||||
#define ARDUINOJSON_VERSION "6.17.0"
|
||||
#define ARDUINOJSON_VERSION_MAJOR 6
|
||||
#define ARDUINOJSON_VERSION_MINOR 16
|
||||
#define ARDUINOJSON_VERSION_REVISION 1
|
||||
#define ARDUINOJSON_VERSION_MINOR 17
|
||||
#define ARDUINOJSON_VERSION_REVISION 0
|
||||
|
||||
@@ -59,7 +59,6 @@ int digitalRead(uint8_t pin);
|
||||
&__c[0]; \
|
||||
}))
|
||||
|
||||
|
||||
class __FlashStringHelper;
|
||||
#define FPSTR(string_literal) (reinterpret_cast<const __FlashStringHelper *>(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 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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user