upgrade arduinojson to 6.17.0

This commit is contained in:
proddy
2020-10-19 23:15:16 +02:00
parent 5235faefff
commit 4fc26dbb44
156 changed files with 10929 additions and 11466 deletions

View File

@@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#include "src/ArduinoJson.h" #include "src/ArduinoJson.h"

View File

@@ -1,6 +1,19 @@
ArduinoJson: change log ArduinoJson: change log
======================= =======================
v6.17.0 (2020-10-19)
-------
* Added a build failure when nullptr is defined as a macro (issue #1355)
* Added `JsonDocument::overflowed()` which tells if the memory pool was too small (issue #1358)
* Added `DeserializationError::EmptyInput` which tells if the input was empty
* Added `DeserializationError::f_str()` which returns a `const __FlashStringHelper*` (issue #846)
* Added `operator|(JsonVariantConst, JsonVariantConst)`
* Added filtering for MessagePack (issue #1298, PR #1394 by Luca Passarella)
* Moved float convertion tables to PROGMEM
* Fixed `JsonVariant::set((char*)0)` which returned false instead of true (issue #1368)
* Fixed error `No such file or directory #include <WString.h>` (issue #1381)
v6.16.1 (2020-08-04) v6.16.1 (2020-08-04)
------- -------
@@ -12,6 +25,7 @@ v6.16.0 (2020-08-01)
* Added comparisons (`>`, `>=`, `==`, `!=`, `<`, and `<=`) between `JsonVariant`s * Added comparisons (`>`, `>=`, `==`, `!=`, `<`, and `<=`) between `JsonVariant`s
* Added string deduplication (issue #1303) * Added string deduplication (issue #1303)
* Added `JsonString::operator!=` * Added `JsonString::operator!=`
* Added wildcard key (`*`) for filters (issue #1309)
* Set `ARDUINOJSON_DECODE_UNICODE` to `1` by default * Set `ARDUINOJSON_DECODE_UNICODE` to `1` by default
* Fixed `copyArray()` not working with `String`, `ElementProxy`, and `MemberProxy` * Fixed `copyArray()` not working with `String`, `ElementProxy`, and `MemberProxy`
* Fixed error `getOrAddElement is not a member of ElementProxy` (issue #1311) * Fixed error `getOrAddElement is not a member of ElementProxy` (issue #1311)

View File

@@ -2,7 +2,7 @@
--- ---
[![arduino-library-badge](https://www.ardu-badge.com/badge/ArduinoJson.svg?version=6.16.1)](https://www.ardu-badge.com/ArduinoJson/6.16.1) [![arduino-library-badge](https://www.ardu-badge.com/badge/ArduinoJson.svg?version=6.17.0)](https://www.ardu-badge.com/ArduinoJson/6.17.0)
[![Build Status](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/6.x?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) [![Build Status](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/6.x?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
[![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=6.x)](https://travis-ci.org/bblanchon/ArduinoJson) [![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=6.x)](https://travis-ci.org/bblanchon/ArduinoJson)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/arduinojson.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson) [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/arduinojson.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson)

View 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!

View File

@@ -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 ❤❤❤❤❤

View File

@@ -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 ❤❤❤❤❤

View File

@@ -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 ❤❤❤❤❤

View File

@@ -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 ❤❤❤❤❤

View File

@@ -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 ❤❤❤❤❤

View File

@@ -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 ❤❤❤❤❤

View File

@@ -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 ❤❤❤❤❤

View File

@@ -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
}

View File

@@ -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 ❤❤❤❤❤

View File

@@ -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 ❤❤❤❤❤

View File

@@ -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

View File

@@ -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

View File

@@ -1,17 +1,17 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#ifdef __cplusplus #ifdef __cplusplus
#include "ArduinoJson.hpp" #include "ArduinoJson.hpp"
using namespace ArduinoJson; using namespace ArduinoJson;
#else #else
#error ArduinoJson requires a C++ compiler, please change file extension to .cc or .cpp #error ArduinoJson requires a C++ compiler, please change file extension to .cc or .cpp
#endif #endif

View File

@@ -1,73 +1,73 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include "ArduinoJson/Configuration.hpp" #include "ArduinoJson/Configuration.hpp"
#if !ARDUINOJSON_DEBUG #if !ARDUINOJSON_DEBUG
#ifdef __clang__ #ifdef __clang__
#pragma clang system_header #pragma clang system_header
#elif defined __GNUC__ #elif defined __GNUC__
#pragma GCC system_header #pragma GCC system_header
#endif #endif
#endif #endif
#include "ArduinoJson/Array/ArrayRef.hpp" #include "ArduinoJson/Array/ArrayRef.hpp"
#include "ArduinoJson/Object/ObjectRef.hpp" #include "ArduinoJson/Object/ObjectRef.hpp"
#include "ArduinoJson/Variant/VariantRef.hpp" #include "ArduinoJson/Variant/VariantRef.hpp"
#include "ArduinoJson/Document/DynamicJsonDocument.hpp" #include "ArduinoJson/Document/DynamicJsonDocument.hpp"
#include "ArduinoJson/Document/StaticJsonDocument.hpp" #include "ArduinoJson/Document/StaticJsonDocument.hpp"
#include "ArduinoJson/Array/ArrayImpl.hpp" #include "ArduinoJson/Array/ArrayImpl.hpp"
#include "ArduinoJson/Array/ElementProxy.hpp" #include "ArduinoJson/Array/ElementProxy.hpp"
#include "ArduinoJson/Array/Utilities.hpp" #include "ArduinoJson/Array/Utilities.hpp"
#include "ArduinoJson/Collection/CollectionImpl.hpp" #include "ArduinoJson/Collection/CollectionImpl.hpp"
#include "ArduinoJson/Object/MemberProxy.hpp" #include "ArduinoJson/Object/MemberProxy.hpp"
#include "ArduinoJson/Object/ObjectImpl.hpp" #include "ArduinoJson/Object/ObjectImpl.hpp"
#include "ArduinoJson/Variant/VariantAsImpl.hpp" #include "ArduinoJson/Variant/VariantAsImpl.hpp"
#include "ArduinoJson/Variant/VariantCompare.hpp" #include "ArduinoJson/Variant/VariantCompare.hpp"
#include "ArduinoJson/Variant/VariantImpl.hpp" #include "ArduinoJson/Variant/VariantImpl.hpp"
#include "ArduinoJson/Json/JsonDeserializer.hpp" #include "ArduinoJson/Json/JsonDeserializer.hpp"
#include "ArduinoJson/Json/JsonSerializer.hpp" #include "ArduinoJson/Json/JsonSerializer.hpp"
#include "ArduinoJson/Json/PrettyJsonSerializer.hpp" #include "ArduinoJson/Json/PrettyJsonSerializer.hpp"
#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp" #include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp" #include "ArduinoJson/MsgPack/MsgPackSerializer.hpp"
#include "ArduinoJson/compatibility.hpp" #include "ArduinoJson/compatibility.hpp"
namespace ArduinoJson { namespace ArduinoJson {
typedef ARDUINOJSON_NAMESPACE::ArrayConstRef JsonArrayConst; typedef ARDUINOJSON_NAMESPACE::ArrayConstRef JsonArrayConst;
typedef ARDUINOJSON_NAMESPACE::ArrayRef JsonArray; typedef ARDUINOJSON_NAMESPACE::ArrayRef JsonArray;
typedef ARDUINOJSON_NAMESPACE::Float JsonFloat; typedef ARDUINOJSON_NAMESPACE::Float JsonFloat;
typedef ARDUINOJSON_NAMESPACE::Integer JsonInteger; typedef ARDUINOJSON_NAMESPACE::Integer JsonInteger;
typedef ARDUINOJSON_NAMESPACE::ObjectConstRef JsonObjectConst; typedef ARDUINOJSON_NAMESPACE::ObjectConstRef JsonObjectConst;
typedef ARDUINOJSON_NAMESPACE::ObjectRef JsonObject; typedef ARDUINOJSON_NAMESPACE::ObjectRef JsonObject;
typedef ARDUINOJSON_NAMESPACE::Pair JsonPair; typedef ARDUINOJSON_NAMESPACE::Pair JsonPair;
typedef ARDUINOJSON_NAMESPACE::PairConst JsonPairConst; typedef ARDUINOJSON_NAMESPACE::PairConst JsonPairConst;
typedef ARDUINOJSON_NAMESPACE::String JsonString; typedef ARDUINOJSON_NAMESPACE::String JsonString;
typedef ARDUINOJSON_NAMESPACE::UInt JsonUInt; typedef ARDUINOJSON_NAMESPACE::UInt JsonUInt;
typedef ARDUINOJSON_NAMESPACE::VariantConstRef JsonVariantConst; typedef ARDUINOJSON_NAMESPACE::VariantConstRef JsonVariantConst;
typedef ARDUINOJSON_NAMESPACE::VariantRef JsonVariant; typedef ARDUINOJSON_NAMESPACE::VariantRef JsonVariant;
using ARDUINOJSON_NAMESPACE::BasicJsonDocument; using ARDUINOJSON_NAMESPACE::BasicJsonDocument;
using ARDUINOJSON_NAMESPACE::copyArray; using ARDUINOJSON_NAMESPACE::copyArray;
using ARDUINOJSON_NAMESPACE::DeserializationError; using ARDUINOJSON_NAMESPACE::DeserializationError;
using ARDUINOJSON_NAMESPACE::deserializeJson; using ARDUINOJSON_NAMESPACE::deserializeJson;
using ARDUINOJSON_NAMESPACE::deserializeMsgPack; using ARDUINOJSON_NAMESPACE::deserializeMsgPack;
using ARDUINOJSON_NAMESPACE::DynamicJsonDocument; using ARDUINOJSON_NAMESPACE::DynamicJsonDocument;
using ARDUINOJSON_NAMESPACE::JsonDocument; using ARDUINOJSON_NAMESPACE::JsonDocument;
using ARDUINOJSON_NAMESPACE::measureJson; using ARDUINOJSON_NAMESPACE::measureJson;
using ARDUINOJSON_NAMESPACE::serialized; using ARDUINOJSON_NAMESPACE::serialized;
using ARDUINOJSON_NAMESPACE::serializeJson; using ARDUINOJSON_NAMESPACE::serializeJson;
using ARDUINOJSON_NAMESPACE::serializeJsonPretty; using ARDUINOJSON_NAMESPACE::serializeJsonPretty;
using ARDUINOJSON_NAMESPACE::serializeMsgPack; using ARDUINOJSON_NAMESPACE::serializeMsgPack;
using ARDUINOJSON_NAMESPACE::StaticJsonDocument; using ARDUINOJSON_NAMESPACE::StaticJsonDocument;
namespace DeserializationOption { namespace DeserializationOption {
using ARDUINOJSON_NAMESPACE::Filter; using ARDUINOJSON_NAMESPACE::Filter;
using ARDUINOJSON_NAMESPACE::NestingLimit; using ARDUINOJSON_NAMESPACE::NestingLimit;
} // namespace DeserializationOption } // namespace DeserializationOption
} // namespace ArduinoJson } // namespace ArduinoJson

View File

@@ -1,30 +1,31 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Collection/CollectionData.hpp> #include <ArduinoJson/Collection/CollectionData.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
inline VariantData *arrayAdd(CollectionData *arr, MemoryPool *pool) { inline VariantData *arrayAdd(CollectionData *arr, MemoryPool *pool) {
return arr ? arr->addElement(pool) : 0; return arr ? arr->addElement(pool) : 0;
} }
template <typename Visitor> template <typename TVisitor>
inline void arrayAccept(const CollectionData *arr, Visitor &visitor) { inline typename TVisitor::result_type arrayAccept(const CollectionData *arr,
if (arr) TVisitor &visitor) {
visitor.visitArray(*arr); if (arr)
else return visitor.visitArray(*arr);
visitor.visitNull(); else
} return visitor.visitNull();
}
inline bool arrayEquals(const CollectionData *lhs, const CollectionData *rhs) {
if (lhs == rhs) inline bool arrayEquals(const CollectionData *lhs, const CollectionData *rhs) {
return true; if (lhs == rhs)
if (!lhs || !rhs) return true;
return false; if (!lhs || !rhs)
return lhs->equalsArray(*rhs); return false;
} return lhs->equalsArray(*rhs);
} // namespace ARDUINOJSON_NAMESPACE }
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,28 +1,28 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Array/ArrayRef.hpp> #include <ArduinoJson/Array/ArrayRef.hpp>
#include <ArduinoJson/Object/ObjectRef.hpp> #include <ArduinoJson/Object/ObjectRef.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename TArray> template <typename TArray>
inline ArrayRef ArrayShortcuts<TArray>::createNestedArray() const { inline ArrayRef ArrayShortcuts<TArray>::createNestedArray() const {
return impl()->addElement().template to<ArrayRef>(); return impl()->addElement().template to<ArrayRef>();
} }
template <typename TArray> template <typename TArray>
inline ObjectRef ArrayShortcuts<TArray>::createNestedObject() const { inline ObjectRef ArrayShortcuts<TArray>::createNestedObject() const {
return impl()->addElement().template to<ObjectRef>(); return impl()->addElement().template to<ObjectRef>();
} }
template <typename TArray> template <typename TArray>
inline ElementProxy<TArray> ArrayShortcuts<TArray>::operator[]( inline ElementProxy<TArray> ArrayShortcuts<TArray>::operator[](
size_t index) const { size_t index) const {
return ElementProxy<TArray>(*impl(), index); return ElementProxy<TArray>(*impl(), index);
} }
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,121 +1,121 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Variant/SlotFunctions.hpp> #include <ArduinoJson/Variant/SlotFunctions.hpp>
#include <ArduinoJson/Variant/VariantRef.hpp> #include <ArduinoJson/Variant/VariantRef.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
class VariantPtr { class VariantPtr {
public: public:
VariantPtr(MemoryPool *pool, VariantData *data) : _variant(pool, data) {} VariantPtr(MemoryPool *pool, VariantData *data) : _variant(pool, data) {}
VariantRef *operator->() { VariantRef *operator->() {
return &_variant; return &_variant;
} }
VariantRef &operator*() { VariantRef &operator*() {
return _variant; return _variant;
} }
private: private:
VariantRef _variant; VariantRef _variant;
}; };
class ArrayIterator { class ArrayIterator {
public: public:
ArrayIterator() : _slot(0) {} ArrayIterator() : _slot(0) {}
explicit ArrayIterator(MemoryPool *pool, VariantSlot *slot) explicit ArrayIterator(MemoryPool *pool, VariantSlot *slot)
: _pool(pool), _slot(slot) {} : _pool(pool), _slot(slot) {}
VariantRef operator*() const { VariantRef operator*() const {
return VariantRef(_pool, _slot->data()); return VariantRef(_pool, _slot->data());
} }
VariantPtr operator->() { VariantPtr operator->() {
return VariantPtr(_pool, _slot->data()); return VariantPtr(_pool, _slot->data());
} }
bool operator==(const ArrayIterator &other) const { bool operator==(const ArrayIterator &other) const {
return _slot == other._slot; return _slot == other._slot;
} }
bool operator!=(const ArrayIterator &other) const { bool operator!=(const ArrayIterator &other) const {
return _slot != other._slot; return _slot != other._slot;
} }
ArrayIterator &operator++() { ArrayIterator &operator++() {
_slot = _slot->next(); _slot = _slot->next();
return *this; return *this;
} }
ArrayIterator &operator+=(size_t distance) { ArrayIterator &operator+=(size_t distance) {
_slot = _slot->next(distance); _slot = _slot->next(distance);
return *this; return *this;
} }
VariantSlot *internal() { VariantSlot *internal() {
return _slot; return _slot;
} }
private: private:
MemoryPool *_pool; MemoryPool *_pool;
VariantSlot *_slot; VariantSlot *_slot;
}; };
class VariantConstPtr { class VariantConstPtr {
public: public:
VariantConstPtr(const VariantData *data) : _variant(data) {} VariantConstPtr(const VariantData *data) : _variant(data) {}
VariantConstRef *operator->() { VariantConstRef *operator->() {
return &_variant; return &_variant;
} }
VariantConstRef &operator*() { VariantConstRef &operator*() {
return _variant; return _variant;
} }
private: private:
VariantConstRef _variant; VariantConstRef _variant;
}; };
class ArrayConstRefIterator { class ArrayConstRefIterator {
public: public:
ArrayConstRefIterator() : _slot(0) {} ArrayConstRefIterator() : _slot(0) {}
explicit ArrayConstRefIterator(const VariantSlot *slot) : _slot(slot) {} explicit ArrayConstRefIterator(const VariantSlot *slot) : _slot(slot) {}
VariantConstRef operator*() const { VariantConstRef operator*() const {
return VariantConstRef(_slot->data()); return VariantConstRef(_slot->data());
} }
VariantConstPtr operator->() { VariantConstPtr operator->() {
return VariantConstPtr(_slot->data()); return VariantConstPtr(_slot->data());
} }
bool operator==(const ArrayConstRefIterator &other) const { bool operator==(const ArrayConstRefIterator &other) const {
return _slot == other._slot; return _slot == other._slot;
} }
bool operator!=(const ArrayConstRefIterator &other) const { bool operator!=(const ArrayConstRefIterator &other) const {
return _slot != other._slot; return _slot != other._slot;
} }
ArrayConstRefIterator &operator++() { ArrayConstRefIterator &operator++() {
_slot = _slot->next(); _slot = _slot->next();
return *this; return *this;
} }
ArrayConstRefIterator &operator+=(size_t distance) { ArrayConstRefIterator &operator+=(size_t distance) {
_slot = _slot->next(distance); _slot = _slot->next(distance);
return *this; return *this;
} }
const VariantSlot *internal() { const VariantSlot *internal() {
return _slot; return _slot;
} }
private: private:
const VariantSlot *_slot; const VariantSlot *_slot;
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,167 +1,167 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Array/ArrayFunctions.hpp> #include <ArduinoJson/Array/ArrayFunctions.hpp>
#include <ArduinoJson/Array/ArrayIterator.hpp> #include <ArduinoJson/Array/ArrayIterator.hpp>
#include <ArduinoJson/Variant/VariantData.hpp> #include <ArduinoJson/Variant/VariantData.hpp>
// Returns the size (in bytes) of an array with n elements. // Returns the size (in bytes) of an array with n elements.
// Can be very handy to determine the size of a StaticMemoryPool. // Can be very handy to determine the size of a StaticMemoryPool.
#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \ #define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot)) ((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot))
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
class ObjectRef; class ObjectRef;
template <typename> template <typename>
class ElementProxy; class ElementProxy;
template <typename TData> template <typename TData>
class ArrayRefBase { class ArrayRefBase {
public: public:
operator VariantConstRef() const { operator VariantConstRef() const {
const void* data = _data; // prevent warning cast-align const void* data = _data; // prevent warning cast-align
return VariantConstRef(reinterpret_cast<const VariantData*>(data)); return VariantConstRef(reinterpret_cast<const VariantData*>(data));
} }
template <typename Visitor> template <typename TVisitor>
FORCE_INLINE void accept(Visitor& visitor) const { FORCE_INLINE typename TVisitor::result_type accept(TVisitor& visitor) const {
arrayAccept(_data, visitor); return arrayAccept(_data, visitor);
} }
FORCE_INLINE bool isNull() const { FORCE_INLINE bool isNull() const {
return _data == 0; return _data == 0;
} }
FORCE_INLINE operator bool() const { FORCE_INLINE operator bool() const {
return _data != 0; return _data != 0;
} }
FORCE_INLINE size_t memoryUsage() const { FORCE_INLINE size_t memoryUsage() const {
return _data ? _data->memoryUsage() : 0; return _data ? _data->memoryUsage() : 0;
} }
FORCE_INLINE size_t nesting() const { FORCE_INLINE size_t nesting() const {
return _data ? _data->nesting() : 0; return _data ? _data->nesting() : 0;
} }
FORCE_INLINE size_t size() const { FORCE_INLINE size_t size() const {
return _data ? _data->size() : 0; return _data ? _data->size() : 0;
} }
protected: protected:
ArrayRefBase(TData* data) : _data(data) {} ArrayRefBase(TData* data) : _data(data) {}
TData* _data; TData* _data;
}; };
class ArrayConstRef : public ArrayRefBase<const CollectionData>, class ArrayConstRef : public ArrayRefBase<const CollectionData>,
public Visitable { public Visitable {
friend class ArrayRef; friend class ArrayRef;
typedef ArrayRefBase<const CollectionData> base_type; typedef ArrayRefBase<const CollectionData> base_type;
public: public:
typedef ArrayConstRefIterator iterator; typedef ArrayConstRefIterator iterator;
FORCE_INLINE iterator begin() const { FORCE_INLINE iterator begin() const {
if (!_data) if (!_data)
return iterator(); return iterator();
return iterator(_data->head()); return iterator(_data->head());
} }
FORCE_INLINE iterator end() const { FORCE_INLINE iterator end() const {
return iterator(); return iterator();
} }
FORCE_INLINE ArrayConstRef() : base_type(0) {} FORCE_INLINE ArrayConstRef() : base_type(0) {}
FORCE_INLINE ArrayConstRef(const CollectionData* data) : base_type(data) {} FORCE_INLINE ArrayConstRef(const CollectionData* data) : base_type(data) {}
FORCE_INLINE bool operator==(ArrayConstRef rhs) const { FORCE_INLINE bool operator==(ArrayConstRef rhs) const {
return arrayEquals(_data, rhs._data); return arrayEquals(_data, rhs._data);
} }
FORCE_INLINE VariantConstRef operator[](size_t index) const { FORCE_INLINE VariantConstRef operator[](size_t index) const {
return getElement(index); return getElement(index);
} }
FORCE_INLINE VariantConstRef getElement(size_t index) const { FORCE_INLINE VariantConstRef getElement(size_t index) const {
return VariantConstRef(_data ? _data->getElement(index) : 0); return VariantConstRef(_data ? _data->getElement(index) : 0);
} }
}; };
class ArrayRef : public ArrayRefBase<CollectionData>, class ArrayRef : public ArrayRefBase<CollectionData>,
public ArrayShortcuts<ArrayRef>, public ArrayShortcuts<ArrayRef>,
public Visitable { public Visitable {
typedef ArrayRefBase<CollectionData> base_type; typedef ArrayRefBase<CollectionData> base_type;
public: public:
typedef ArrayIterator iterator; typedef ArrayIterator iterator;
FORCE_INLINE ArrayRef() : base_type(0), _pool(0) {} FORCE_INLINE ArrayRef() : base_type(0), _pool(0) {}
FORCE_INLINE ArrayRef(MemoryPool* pool, CollectionData* data) FORCE_INLINE ArrayRef(MemoryPool* pool, CollectionData* data)
: base_type(data), _pool(pool) {} : base_type(data), _pool(pool) {}
operator VariantRef() { operator VariantRef() {
void* data = _data; // prevent warning cast-align void* data = _data; // prevent warning cast-align
return VariantRef(_pool, reinterpret_cast<VariantData*>(data)); return VariantRef(_pool, reinterpret_cast<VariantData*>(data));
} }
operator ArrayConstRef() const { operator ArrayConstRef() const {
return ArrayConstRef(_data); return ArrayConstRef(_data);
} }
VariantRef addElement() const { VariantRef addElement() const {
return VariantRef(_pool, arrayAdd(_data, _pool)); return VariantRef(_pool, arrayAdd(_data, _pool));
} }
FORCE_INLINE iterator begin() const { FORCE_INLINE iterator begin() const {
if (!_data) if (!_data)
return iterator(); return iterator();
return iterator(_pool, _data->head()); return iterator(_pool, _data->head());
} }
FORCE_INLINE iterator end() const { FORCE_INLINE iterator end() const {
return iterator(); return iterator();
} }
// Copy a ArrayRef // Copy a ArrayRef
FORCE_INLINE bool set(ArrayConstRef src) const { FORCE_INLINE bool set(ArrayConstRef src) const {
if (!_data || !src._data) if (!_data || !src._data)
return false; return false;
return _data->copyFrom(*src._data, _pool); return _data->copyFrom(*src._data, _pool);
} }
FORCE_INLINE bool operator==(ArrayRef rhs) const { FORCE_INLINE bool operator==(ArrayRef rhs) const {
return arrayEquals(_data, rhs._data); return arrayEquals(_data, rhs._data);
} }
// Internal use // Internal use
FORCE_INLINE VariantRef getOrAddElement(size_t index) const { FORCE_INLINE VariantRef getOrAddElement(size_t index) const {
return VariantRef(_pool, _data ? _data->getOrAddElement(index, _pool) : 0); return VariantRef(_pool, _data ? _data->getOrAddElement(index, _pool) : 0);
} }
// Gets the value at the specified index. // Gets the value at the specified index.
FORCE_INLINE VariantRef getElement(size_t index) const { FORCE_INLINE VariantRef getElement(size_t index) const {
return VariantRef(_pool, _data ? _data->getElement(index) : 0); return VariantRef(_pool, _data ? _data->getElement(index) : 0);
} }
// Removes element at specified position. // Removes element at specified position.
FORCE_INLINE void remove(iterator it) const { FORCE_INLINE void remove(iterator it) const {
if (!_data) if (!_data)
return; return;
_data->removeSlot(it.internal()); _data->removeSlot(it.internal());
} }
// Removes element at specified index. // Removes element at specified index.
FORCE_INLINE void remove(size_t index) const { FORCE_INLINE void remove(size_t index) const {
if (!_data) if (!_data)
return; return;
_data->removeElement(index); _data->removeElement(index);
} }
private: private:
MemoryPool* _pool; MemoryPool* _pool;
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

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

View File

@@ -1,178 +1,178 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Configuration.hpp> #include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Variant/VariantOperators.hpp> #include <ArduinoJson/Variant/VariantOperators.hpp>
#include <ArduinoJson/Variant/VariantShortcuts.hpp> #include <ArduinoJson/Variant/VariantShortcuts.hpp>
#include <ArduinoJson/Variant/VariantTo.hpp> #include <ArduinoJson/Variant/VariantTo.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4522) #pragma warning(disable : 4522)
#endif #endif
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename TArray> template <typename TArray>
class ElementProxy : public VariantOperators<ElementProxy<TArray> >, class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
public VariantShortcuts<ElementProxy<TArray> >, public VariantShortcuts<ElementProxy<TArray> >,
public Visitable { public Visitable {
typedef ElementProxy<TArray> this_type; typedef ElementProxy<TArray> this_type;
public: public:
FORCE_INLINE ElementProxy(TArray array, size_t index) FORCE_INLINE ElementProxy(TArray array, size_t index)
: _array(array), _index(index) {} : _array(array), _index(index) {}
FORCE_INLINE ElementProxy(const ElementProxy& src) FORCE_INLINE ElementProxy(const ElementProxy& src)
: _array(src._array), _index(src._index) {} : _array(src._array), _index(src._index) {}
FORCE_INLINE this_type& operator=(const this_type& src) { FORCE_INLINE this_type& operator=(const this_type& src) {
getOrAddUpstreamElement().set(src.as<VariantConstRef>()); getOrAddUpstreamElement().set(src.as<VariantConstRef>());
return *this; return *this;
} }
// Replaces the value // Replaces the value
// //
// operator=(const TValue&) // operator=(const TValue&)
// TValue = bool, long, int, short, float, double, serialized, VariantRef, // TValue = bool, long, int, short, float, double, serialized, VariantRef,
// std::string, String, ArrayRef, ObjectRef // std::string, String, ArrayRef, ObjectRef
template <typename T> template <typename T>
FORCE_INLINE this_type& operator=(const T& src) { FORCE_INLINE this_type& operator=(const T& src) {
getOrAddUpstreamElement().set(src); getOrAddUpstreamElement().set(src);
return *this; return *this;
} }
// //
// operator=(TValue) // operator=(TValue)
// TValue = char*, const char*, const __FlashStringHelper* // TValue = char*, const char*, const __FlashStringHelper*
template <typename T> template <typename T>
FORCE_INLINE this_type& operator=(T* src) { FORCE_INLINE this_type& operator=(T* src) {
getOrAddUpstreamElement().set(src); getOrAddUpstreamElement().set(src);
return *this; return *this;
} }
FORCE_INLINE void clear() const { FORCE_INLINE void clear() const {
getUpstreamElement().clear(); getUpstreamElement().clear();
} }
FORCE_INLINE bool isNull() const { FORCE_INLINE bool isNull() const {
return getUpstreamElement().isNull(); return getUpstreamElement().isNull();
} }
template <typename T> template <typename T>
FORCE_INLINE typename VariantAs<T>::type as() const { FORCE_INLINE typename VariantAs<T>::type as() const {
return getUpstreamElement().template as<T>(); return getUpstreamElement().template as<T>();
} }
template <typename T> template <typename T>
FORCE_INLINE operator T() const { FORCE_INLINE operator T() const {
return getUpstreamElement(); return getUpstreamElement();
} }
template <typename T> template <typename T>
FORCE_INLINE bool is() const { FORCE_INLINE bool is() const {
return getUpstreamElement().template is<T>(); return getUpstreamElement().template is<T>();
} }
template <typename T> template <typename T>
FORCE_INLINE typename VariantTo<T>::type to() const { FORCE_INLINE typename VariantTo<T>::type to() const {
return getOrAddUpstreamElement().template to<T>(); return getOrAddUpstreamElement().template to<T>();
} }
// Replaces the value // Replaces the value
// //
// bool set(const TValue&) // bool set(const TValue&)
// TValue = bool, long, int, short, float, double, serialized, VariantRef, // TValue = bool, long, int, short, float, double, serialized, VariantRef,
// std::string, String, ArrayRef, ObjectRef // std::string, String, ArrayRef, ObjectRef
template <typename TValue> template <typename TValue>
FORCE_INLINE bool set(const TValue& value) const { FORCE_INLINE bool set(const TValue& value) const {
return getOrAddUpstreamElement().set(value); return getOrAddUpstreamElement().set(value);
} }
// //
// bool set(TValue) // bool set(TValue)
// TValue = char*, const char*, const __FlashStringHelper* // TValue = char*, const char*, const __FlashStringHelper*
template <typename TValue> template <typename TValue>
FORCE_INLINE bool set(TValue* value) const { FORCE_INLINE bool set(TValue* value) const {
return getOrAddUpstreamElement().set(value); return getOrAddUpstreamElement().set(value);
} }
template <typename Visitor> template <typename TVisitor>
void accept(Visitor& visitor) const { typename TVisitor::result_type accept(TVisitor& visitor) const {
return getUpstreamElement().accept(visitor); return getUpstreamElement().accept(visitor);
} }
FORCE_INLINE size_t size() const { FORCE_INLINE size_t size() const {
return getUpstreamElement().size(); return getUpstreamElement().size();
} }
template <typename TNestedKey> template <typename TNestedKey>
VariantRef getMember(TNestedKey* key) const { VariantRef getMember(TNestedKey* key) const {
return getUpstreamElement().getMember(key); return getUpstreamElement().getMember(key);
} }
template <typename TNestedKey> template <typename TNestedKey>
VariantRef getMember(const TNestedKey& key) const { VariantRef getMember(const TNestedKey& key) const {
return getUpstreamElement().getMember(key); return getUpstreamElement().getMember(key);
} }
template <typename TNestedKey> template <typename TNestedKey>
VariantRef getOrAddMember(TNestedKey* key) const { VariantRef getOrAddMember(TNestedKey* key) const {
return getOrAddUpstreamElement().getOrAddMember(key); return getOrAddUpstreamElement().getOrAddMember(key);
} }
template <typename TNestedKey> template <typename TNestedKey>
VariantRef getOrAddMember(const TNestedKey& key) const { VariantRef getOrAddMember(const TNestedKey& key) const {
return getOrAddUpstreamElement().getOrAddMember(key); return getOrAddUpstreamElement().getOrAddMember(key);
} }
VariantRef addElement() const { VariantRef addElement() const {
return getOrAddUpstreamElement().addElement(); return getOrAddUpstreamElement().addElement();
} }
VariantRef getElement(size_t index) const { VariantRef getElement(size_t index) const {
return getOrAddUpstreamElement().getElement(index); return getOrAddUpstreamElement().getElement(index);
} }
VariantRef getOrAddElement(size_t index) const { VariantRef getOrAddElement(size_t index) const {
return getOrAddUpstreamElement().getOrAddElement(index); return getOrAddUpstreamElement().getOrAddElement(index);
} }
FORCE_INLINE void remove(size_t index) const { FORCE_INLINE void remove(size_t index) const {
getUpstreamElement().remove(index); getUpstreamElement().remove(index);
} }
// remove(char*) const // remove(char*) const
// remove(const char*) const // remove(const char*) const
// remove(const __FlashStringHelper*) const // remove(const __FlashStringHelper*) const
template <typename TChar> template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove( FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove(
TChar* key) const { TChar* key) const {
getUpstreamElement().remove(key); getUpstreamElement().remove(key);
} }
// remove(const std::string&) const // remove(const std::string&) const
// remove(const String&) const // remove(const String&) const
template <typename TString> template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove( FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
const TString& key) const { const TString& key) const {
getUpstreamElement().remove(key); getUpstreamElement().remove(key);
} }
private: private:
FORCE_INLINE VariantRef getUpstreamElement() const { FORCE_INLINE VariantRef getUpstreamElement() const {
return _array.getElement(_index); return _array.getElement(_index);
} }
FORCE_INLINE VariantRef getOrAddUpstreamElement() const { FORCE_INLINE VariantRef getOrAddUpstreamElement() const {
return _array.getOrAddElement(_index); return _array.getOrAddElement(_index);
} }
TArray _array; TArray _array;
const size_t _index; const size_t _index;
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif

View File

@@ -1,150 +1,171 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Array/ArrayRef.hpp> #include <ArduinoJson/Array/ArrayRef.hpp>
#include <ArduinoJson/Document/JsonDocument.hpp> #include <ArduinoJson/Document/JsonDocument.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
// Copy a 1D array to a JsonArray // Copy a 1D array to a JsonArray
template <typename T, size_t N, typename TDestination> template <typename T, size_t N, typename TDestination>
inline typename enable_if<!is_array<T>::value && inline typename enable_if<!is_array<T>::value &&
!is_base_of<JsonDocument, TDestination>::value, !is_base_of<JsonDocument, TDestination>::value,
bool>::type bool>::type
copyArray(T (&src)[N], const TDestination& dst) { copyArray(T (&src)[N], const TDestination& dst) {
return copyArray(src, N, dst); return copyArray(src, N, dst);
} }
// Copy a 1D array to a JsonDocument // Copy a 1D array to a JsonDocument
template <typename T, size_t N> template <typename T, size_t N>
inline bool copyArray(T (&src)[N], JsonDocument& dst) { inline bool copyArray(T (&src)[N], JsonDocument& dst) {
return copyArray(src, dst.to<ArrayRef>()); return copyArray(src, dst.to<ArrayRef>());
} }
// Copy a 1D array to a JsonArray // Copy a 1D array to a JsonArray
template <typename T, typename TDestination> template <typename T, typename TDestination>
inline typename enable_if<!is_array<T>::value && inline typename enable_if<!is_array<T>::value &&
!is_base_of<JsonDocument, TDestination>::value, !is_base_of<JsonDocument, TDestination>::value,
bool>::type bool>::type
copyArray(T* src, size_t len, const TDestination& dst) { copyArray(T* src, size_t len, const TDestination& dst) {
bool ok = true; bool ok = true;
for (size_t i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
ok &= dst.add(src[i]); ok &= dst.add(src[i]);
} }
return ok; return ok;
} }
// Copy a 1D array to a JsonDocument // Copy a 1D array to a JsonDocument
template <typename T> template <typename T>
inline bool copyArray(T* src, size_t len, JsonDocument& dst) { inline bool copyArray(T* src, size_t len, JsonDocument& dst) {
return copyArray(src, len, dst.to<ArrayRef>()); return copyArray(src, len, dst.to<ArrayRef>());
} }
// Copy a 2D array to a JsonArray // Copy a 2D array to a JsonArray
template <typename T, size_t N1, size_t N2, typename TDestination> template <typename T, size_t N1, size_t N2, typename TDestination>
inline typename enable_if<!is_base_of<JsonDocument, TDestination>::value, inline typename enable_if<!is_base_of<JsonDocument, TDestination>::value,
bool>::type bool>::type
copyArray(T (&src)[N1][N2], const TDestination& dst) { copyArray(T (&src)[N1][N2], const TDestination& dst) {
bool ok = true; bool ok = true;
for (size_t i = 0; i < N1; i++) { for (size_t i = 0; i < N1; i++) {
ArrayRef nestedArray = dst.createNestedArray(); ArrayRef nestedArray = dst.createNestedArray();
for (size_t j = 0; j < N2; j++) { for (size_t j = 0; j < N2; j++) {
ok &= nestedArray.add(src[i][j]); ok &= nestedArray.add(src[i][j]);
} }
} }
return ok; return ok;
} }
// Copy a 2D array to a JsonDocument // Copy a 2D array to a JsonDocument
template <typename T, size_t N1, size_t N2> template <typename T, size_t N1, size_t N2>
inline bool copyArray(T (&src)[N1][N2], JsonDocument& dst) { inline bool copyArray(T (&src)[N1][N2], JsonDocument& dst) {
return copyArray(src, dst.to<ArrayRef>()); return copyArray(src, dst.to<ArrayRef>());
} }
template <typename T> template <typename T>
class ArrayCopier1D { class ArrayCopier1D : public Visitor<size_t> {
public: public:
ArrayCopier1D(T* destination, size_t capacity) ArrayCopier1D(T* destination, size_t capacity)
: _destination(destination), _capacity(capacity), _size(0) {} : _destination(destination), _capacity(capacity) {}
void visitArray(const CollectionData& array) { size_t visitArray(const CollectionData& array) {
VariantSlot* slot = array.head(); size_t size = 0;
VariantSlot* slot = array.head();
while (slot != 0 && _size < _capacity) {
_destination[_size++] = variantAs<T>(slot->data()); while (slot != 0 && size < _capacity) {
slot = slot->next(); _destination[size++] = variantAs<T>(slot->data());
} slot = slot->next();
} }
void visitObject(const CollectionData&) {} return size;
void visitFloat(Float) {} }
void visitString(const char*) {}
void visitRawJson(const char*, size_t) {} size_t visitObject(const CollectionData&) {
void visitNegativeInteger(UInt) {} return 0;
void visitPositiveInteger(UInt) {} }
void visitBoolean(bool) {}
void visitNull() {} size_t visitFloat(Float) {
return 0;
size_t result() const { }
return _size;
} size_t visitString(const char*) {
return 0;
private: }
T* _destination;
size_t _capacity; size_t visitRawJson(const char*, size_t) {
size_t _size; return 0;
}; }
template <typename T, size_t N1, size_t N2> size_t visitNegativeInteger(UInt) {
class ArrayCopier2D { return 0;
public: }
ArrayCopier2D(T (*destination)[N1][N2]) : _destination(destination) {}
size_t visitPositiveInteger(UInt) {
void visitArray(const CollectionData& array) { return 0;
VariantSlot* slot = array.head(); }
size_t n = 0;
while (slot != 0 && n < N1) { size_t visitBoolean(bool) {
ArrayCopier1D<T> copier((*_destination)[n++], N2); return 0;
variantAccept(slot->data(), copier); }
slot = slot->next();
} size_t visitNull() {
} return 0;
void visitObject(const CollectionData&) {} }
void visitFloat(Float) {}
void visitString(const char*) {} private:
void visitRawJson(const char*, size_t) {} T* _destination;
void visitNegativeInteger(UInt) {} size_t _capacity;
void visitPositiveInteger(UInt) {} };
void visitBoolean(bool) {}
void visitNull() {} template <typename T, size_t N1, size_t N2>
class ArrayCopier2D : public Visitor<void> {
private: public:
T (*_destination)[N1][N2]; ArrayCopier2D(T (*destination)[N1][N2]) : _destination(destination) {}
size_t _capacity1, _capacity2;
}; void visitArray(const CollectionData& array) {
VariantSlot* slot = array.head();
// Copy a JsonArray to a 1D array size_t n = 0;
template <typename TSource, typename T, size_t N> while (slot != 0 && n < N1) {
inline typename enable_if<!is_array<T>::value, size_t>::type copyArray( ArrayCopier1D<T> copier((*_destination)[n++], N2);
const TSource& src, T (&dst)[N]) { variantAccept(slot->data(), copier);
return copyArray(src, dst, N); slot = slot->next();
} }
}
// Copy a JsonArray to a 1D array void visitObject(const CollectionData&) {}
template <typename TSource, typename T> void visitFloat(Float) {}
inline size_t copyArray(const TSource& src, T* dst, size_t len) { void visitString(const char*) {}
ArrayCopier1D<T> copier(dst, len); void visitRawJson(const char*, size_t) {}
src.accept(copier); void visitNegativeInteger(UInt) {}
return copier.result(); void visitPositiveInteger(UInt) {}
} void visitBoolean(bool) {}
void visitNull() {}
// Copy a JsonArray to a 2D array
template <typename TSource, typename T, size_t N1, size_t N2> private:
inline void copyArray(const TSource& src, T (&dst)[N1][N2]) { T (*_destination)[N1][N2];
ArrayCopier2D<T, N1, N2> copier(&dst); size_t _capacity1, _capacity2;
src.accept(copier); };
}
// Copy a JsonArray to a 1D array
} // namespace ARDUINOJSON_NAMESPACE template <typename TSource, typename T, size_t N>
inline typename enable_if<!is_array<T>::value, size_t>::type copyArray(
const TSource& src, T (&dst)[N]) {
return copyArray(src, dst, N);
}
// Copy a JsonArray to a 1D array
template <typename TSource, typename T>
inline size_t copyArray(const TSource& src, T* dst, size_t len) {
ArrayCopier1D<T> copier(dst, len);
return src.accept(copier);
}
// Copy a JsonArray to a 2D array
template <typename TSource, typename T, size_t N1, size_t N2>
inline void copyArray(const TSource& src, T (&dst)[N1][N2]) {
ArrayCopier2D<T, N1, N2> copier(&dst);
src.accept(copier);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,88 +1,88 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
#include <ArduinoJson/Polyfills/assert.hpp> #include <ArduinoJson/Polyfills/assert.hpp>
#include <stddef.h> // size_t #include <stddef.h> // size_t
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
class MemoryPool; class MemoryPool;
class VariantData; class VariantData;
class VariantSlot; class VariantSlot;
class CollectionData { class CollectionData {
VariantSlot *_head; VariantSlot *_head;
VariantSlot *_tail; VariantSlot *_tail;
public: public:
// Must be a POD! // Must be a POD!
// - no constructor // - no constructor
// - no destructor // - no destructor
// - no virtual // - no virtual
// - no inheritance // - no inheritance
// Array only // Array only
VariantData *addElement(MemoryPool *pool); VariantData *addElement(MemoryPool *pool);
VariantData *getElement(size_t index) const; VariantData *getElement(size_t index) const;
VariantData *getOrAddElement(size_t index, MemoryPool *pool); VariantData *getOrAddElement(size_t index, MemoryPool *pool);
void removeElement(size_t index); void removeElement(size_t index);
bool equalsArray(const CollectionData &other) const; bool equalsArray(const CollectionData &other) const;
// Object only // Object only
template <typename TAdaptedString> template <typename TAdaptedString>
VariantData *addMember(TAdaptedString key, MemoryPool *pool); VariantData *addMember(TAdaptedString key, MemoryPool *pool);
template <typename TAdaptedString> template <typename TAdaptedString>
VariantData *getMember(TAdaptedString key) const; VariantData *getMember(TAdaptedString key) const;
template <typename TAdaptedString> template <typename TAdaptedString>
VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool); VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool);
template <typename TAdaptedString> template <typename TAdaptedString>
void removeMember(TAdaptedString key) { void removeMember(TAdaptedString key) {
removeSlot(getSlot(key)); removeSlot(getSlot(key));
} }
template <typename TAdaptedString> template <typename TAdaptedString>
bool containsKey(const TAdaptedString &key) const; bool containsKey(const TAdaptedString &key) const;
bool equalsObject(const CollectionData &other) const; bool equalsObject(const CollectionData &other) const;
// Generic // Generic
void clear(); void clear();
size_t memoryUsage() const; size_t memoryUsage() const;
size_t nesting() const; size_t nesting() const;
size_t size() const; size_t size() const;
VariantSlot *addSlot(MemoryPool *); VariantSlot *addSlot(MemoryPool *);
void removeSlot(VariantSlot *slot); void removeSlot(VariantSlot *slot);
bool copyFrom(const CollectionData &src, MemoryPool *pool); bool copyFrom(const CollectionData &src, MemoryPool *pool);
VariantSlot *head() const { VariantSlot *head() const {
return _head; return _head;
} }
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance); void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance);
private: private:
VariantSlot *getSlot(size_t index) const; VariantSlot *getSlot(size_t index) const;
template <typename TAdaptedString> template <typename TAdaptedString>
VariantSlot *getSlot(TAdaptedString key) const; VariantSlot *getSlot(TAdaptedString key) const;
VariantSlot *getPreviousSlot(VariantSlot *) const; VariantSlot *getPreviousSlot(VariantSlot *) const;
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,232 +1,232 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Collection/CollectionData.hpp> #include <ArduinoJson/Collection/CollectionData.hpp>
#include <ArduinoJson/Variant/VariantData.hpp> #include <ArduinoJson/Variant/VariantData.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
inline bool variantEquals(const VariantData* a, const VariantData* b) { inline bool variantEquals(const VariantData* a, const VariantData* b) {
return variantCompare(a, b) == COMPARE_RESULT_EQUAL; return variantCompare(a, b) == COMPARE_RESULT_EQUAL;
} }
inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) { inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) {
VariantSlot* slot = pool->allocVariant(); VariantSlot* slot = pool->allocVariant();
if (!slot) if (!slot)
return 0; return 0;
if (_tail) { if (_tail) {
_tail->setNextNotNull(slot); _tail->setNextNotNull(slot);
_tail = slot; _tail = slot;
} else { } else {
_head = slot; _head = slot;
_tail = slot; _tail = slot;
} }
slot->clear(); slot->clear();
return slot; return slot;
} }
inline VariantData* CollectionData::addElement(MemoryPool* pool) { inline VariantData* CollectionData::addElement(MemoryPool* pool) {
return slotData(addSlot(pool)); return slotData(addSlot(pool));
} }
template <typename TAdaptedString> template <typename TAdaptedString>
inline VariantData* CollectionData::addMember(TAdaptedString key, inline VariantData* CollectionData::addMember(TAdaptedString key,
MemoryPool* pool) { MemoryPool* pool) {
VariantSlot* slot = addSlot(pool); VariantSlot* slot = addSlot(pool);
if (!slotSetKey(slot, key, pool)) { if (!slotSetKey(slot, key, pool)) {
removeSlot(slot); removeSlot(slot);
return 0; return 0;
} }
return slot->data(); return slot->data();
} }
inline void CollectionData::clear() { inline void CollectionData::clear() {
_head = 0; _head = 0;
_tail = 0; _tail = 0;
} }
template <typename TAdaptedString> template <typename TAdaptedString>
inline bool CollectionData::containsKey(const TAdaptedString& key) const { inline bool CollectionData::containsKey(const TAdaptedString& key) const {
return getSlot(key) != 0; return getSlot(key) != 0;
} }
inline bool CollectionData::copyFrom(const CollectionData& src, inline bool CollectionData::copyFrom(const CollectionData& src,
MemoryPool* pool) { MemoryPool* pool) {
clear(); clear();
for (VariantSlot* s = src._head; s; s = s->next()) { for (VariantSlot* s = src._head; s; s = s->next()) {
VariantData* var; VariantData* var;
if (s->key() != 0) { if (s->key() != 0) {
if (s->ownsKey()) if (s->ownsKey())
var = addMember(RamStringAdapter(s->key()), pool); var = addMember(RamStringAdapter(s->key()), pool);
else else
var = addMember(ConstRamStringAdapter(s->key()), pool); var = addMember(ConstRamStringAdapter(s->key()), pool);
} else { } else {
var = addElement(pool); var = addElement(pool);
} }
if (!var) if (!var)
return false; return false;
if (!var->copyFrom(*s->data(), pool)) if (!var->copyFrom(*s->data(), pool))
return false; return false;
} }
return true; return true;
} }
inline bool CollectionData::equalsObject(const CollectionData& other) const { inline bool CollectionData::equalsObject(const CollectionData& other) const {
size_t count = 0; size_t count = 0;
for (VariantSlot* slot = _head; slot; slot = slot->next()) { for (VariantSlot* slot = _head; slot; slot = slot->next()) {
VariantData* v1 = slot->data(); VariantData* v1 = slot->data();
VariantData* v2 = other.getMember(adaptString(slot->key())); VariantData* v2 = other.getMember(adaptString(slot->key()));
if (!variantEquals(v1, v2)) if (!variantEquals(v1, v2))
return false; return false;
count++; count++;
} }
return count == other.size(); return count == other.size();
} }
inline bool CollectionData::equalsArray(const CollectionData& other) const { inline bool CollectionData::equalsArray(const CollectionData& other) const {
VariantSlot* s1 = _head; VariantSlot* s1 = _head;
VariantSlot* s2 = other._head; VariantSlot* s2 = other._head;
for (;;) { for (;;) {
if (s1 == s2) if (s1 == s2)
return true; return true;
if (!s1 || !s2) if (!s1 || !s2)
return false; return false;
if (!variantEquals(s1->data(), s2->data())) if (!variantEquals(s1->data(), s2->data()))
return false; return false;
s1 = s1->next(); s1 = s1->next();
s2 = s2->next(); s2 = s2->next();
} }
} }
template <typename TAdaptedString> template <typename TAdaptedString>
inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const { inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const {
VariantSlot* slot = _head; VariantSlot* slot = _head;
while (slot) { while (slot) {
if (key.equals(slot->key())) if (key.equals(slot->key()))
break; break;
slot = slot->next(); slot = slot->next();
} }
return slot; return slot;
} }
inline VariantSlot* CollectionData::getSlot(size_t index) const { inline VariantSlot* CollectionData::getSlot(size_t index) const {
return _head->next(index); return _head->next(index);
} }
inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const { inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const {
VariantSlot* current = _head; VariantSlot* current = _head;
while (current) { while (current) {
VariantSlot* next = current->next(); VariantSlot* next = current->next();
if (next == target) if (next == target)
return current; return current;
current = next; current = next;
} }
return 0; return 0;
} }
template <typename TAdaptedString> template <typename TAdaptedString>
inline VariantData* CollectionData::getMember(TAdaptedString key) const { inline VariantData* CollectionData::getMember(TAdaptedString key) const {
VariantSlot* slot = getSlot(key); VariantSlot* slot = getSlot(key);
return slot ? slot->data() : 0; return slot ? slot->data() : 0;
} }
template <typename TAdaptedString> template <typename TAdaptedString>
inline VariantData* CollectionData::getOrAddMember(TAdaptedString key, inline VariantData* CollectionData::getOrAddMember(TAdaptedString key,
MemoryPool* pool) { MemoryPool* pool) {
// ignore null key // ignore null key
if (key.isNull()) if (key.isNull())
return 0; return 0;
// search a matching key // search a matching key
VariantSlot* slot = getSlot(key); VariantSlot* slot = getSlot(key);
if (slot) if (slot)
return slot->data(); return slot->data();
return addMember(key, pool); return addMember(key, pool);
} }
inline VariantData* CollectionData::getElement(size_t index) const { inline VariantData* CollectionData::getElement(size_t index) const {
VariantSlot* slot = getSlot(index); VariantSlot* slot = getSlot(index);
return slot ? slot->data() : 0; return slot ? slot->data() : 0;
} }
inline VariantData* CollectionData::getOrAddElement(size_t index, inline VariantData* CollectionData::getOrAddElement(size_t index,
MemoryPool* pool) { MemoryPool* pool) {
VariantSlot* slot = _head; VariantSlot* slot = _head;
while (slot && index > 0) { while (slot && index > 0) {
slot = slot->next(); slot = slot->next();
index--; index--;
} }
if (!slot) if (!slot)
index++; index++;
while (index > 0) { while (index > 0) {
slot = addSlot(pool); slot = addSlot(pool);
index--; index--;
} }
return slotData(slot); return slotData(slot);
} }
inline void CollectionData::removeSlot(VariantSlot* slot) { inline void CollectionData::removeSlot(VariantSlot* slot) {
if (!slot) if (!slot)
return; return;
VariantSlot* prev = getPreviousSlot(slot); VariantSlot* prev = getPreviousSlot(slot);
VariantSlot* next = slot->next(); VariantSlot* next = slot->next();
if (prev) if (prev)
prev->setNext(next); prev->setNext(next);
else else
_head = next; _head = next;
if (!next) if (!next)
_tail = prev; _tail = prev;
} }
inline void CollectionData::removeElement(size_t index) { inline void CollectionData::removeElement(size_t index) {
removeSlot(getSlot(index)); removeSlot(getSlot(index));
} }
inline size_t CollectionData::memoryUsage() const { inline size_t CollectionData::memoryUsage() const {
size_t total = 0; size_t total = 0;
for (VariantSlot* s = _head; s; s = s->next()) { for (VariantSlot* s = _head; s; s = s->next()) {
total += sizeof(VariantSlot) + s->data()->memoryUsage(); total += sizeof(VariantSlot) + s->data()->memoryUsage();
if (s->ownsKey()) if (s->ownsKey())
total += strlen(s->key()) + 1; total += strlen(s->key()) + 1;
} }
return total; return total;
} }
inline size_t CollectionData::nesting() const { inline size_t CollectionData::nesting() const {
size_t maxChildNesting = 0; size_t maxChildNesting = 0;
for (VariantSlot* s = _head; s; s = s->next()) { for (VariantSlot* s = _head; s; s = s->next()) {
size_t childNesting = s->data()->nesting(); size_t childNesting = s->data()->nesting();
if (childNesting > maxChildNesting) if (childNesting > maxChildNesting)
maxChildNesting = childNesting; maxChildNesting = childNesting;
} }
return maxChildNesting + 1; return maxChildNesting + 1;
} }
inline size_t CollectionData::size() const { inline size_t CollectionData::size() const {
return slotSize(_head); return slotSize(_head);
} }
template <typename T> template <typename T>
inline void movePointer(T*& p, ptrdiff_t offset) { inline void movePointer(T*& p, ptrdiff_t offset) {
if (!p) if (!p)
return; return;
p = reinterpret_cast<T*>( p = reinterpret_cast<T*>(
reinterpret_cast<void*>(reinterpret_cast<char*>(p) + offset)); reinterpret_cast<void*>(reinterpret_cast<char*>(p) + offset));
ARDUINOJSON_ASSERT(isAligned(p)); ARDUINOJSON_ASSERT(isAligned(p));
} }
inline void CollectionData::movePointers(ptrdiff_t stringDistance, inline void CollectionData::movePointers(ptrdiff_t stringDistance,
ptrdiff_t variantDistance) { ptrdiff_t variantDistance) {
movePointer(_head, variantDistance); movePointer(_head, variantDistance);
movePointer(_tail, variantDistance); movePointer(_tail, variantDistance);
for (VariantSlot* slot = _head; slot; slot = slot->next()) for (VariantSlot* slot = _head; slot; slot = slot->next())
slot->movePointers(stringDistance, variantDistance); slot->movePointers(stringDistance, variantDistance);
} }
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,232 +1,237 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
#define ARDUINOJSON_HAS_LONG_LONG 1 #define ARDUINOJSON_HAS_LONG_LONG 1
#define ARDUINOJSON_HAS_NULLPTR 1 #define ARDUINOJSON_HAS_NULLPTR 1
#define ARDUINOJSON_HAS_RVALUE_REFERENCES 1 #define ARDUINOJSON_HAS_RVALUE_REFERENCES 1
#else #else
#define ARDUINOJSON_HAS_LONG_LONG 0 #define ARDUINOJSON_HAS_LONG_LONG 0
#define ARDUINOJSON_HAS_NULLPTR 0 #define ARDUINOJSON_HAS_NULLPTR 0
#define ARDUINOJSON_HAS_RVALUE_REFERENCES 0 #define ARDUINOJSON_HAS_RVALUE_REFERENCES 0
#endif #endif
#if defined(_MSC_VER) && !ARDUINOJSON_HAS_LONG_LONG #if defined(_MSC_VER) && !ARDUINOJSON_HAS_LONG_LONG
#define ARDUINOJSON_HAS_INT64 1 #define ARDUINOJSON_HAS_INT64 1
#else #else
#define ARDUINOJSON_HAS_INT64 0 #define ARDUINOJSON_HAS_INT64 0
#endif #endif
// Small or big machine? // Small or big machine?
#ifndef ARDUINOJSON_EMBEDDED_MODE #ifndef ARDUINOJSON_EMBEDDED_MODE
#if defined(ARDUINO) /* Arduino*/ \ #if defined(ARDUINO) /* Arduino*/ \
|| defined(__IAR_SYSTEMS_ICC__) /* IAR Embedded Workbench */ \ || defined(__IAR_SYSTEMS_ICC__) /* IAR Embedded Workbench */ \
|| defined(__XC) /* MPLAB XC compiler */ \ || defined(__XC) /* MPLAB XC compiler */ \
|| defined(__ARMCC_VERSION) /* Keil ARM Compiler */ \ || defined(__ARMCC_VERSION) /* Keil ARM Compiler */ \
|| defined(__AVR) /* Atmel AVR8/GNU C Compiler */ || defined(__AVR) /* Atmel AVR8/GNU C Compiler */
#define ARDUINOJSON_EMBEDDED_MODE 1 #define ARDUINOJSON_EMBEDDED_MODE 1
#else #else
#define ARDUINOJSON_EMBEDDED_MODE 0 #define ARDUINOJSON_EMBEDDED_MODE 0
#endif #endif
#endif #endif
// Auto enable std::stream if the right headers are here and no conflicting // Auto enable std::stream if the right headers are here and no conflicting
// macro is defined // macro is defined
#if !defined(ARDUINOJSON_ENABLE_STD_STREAM) && defined(__has_include) #if !defined(ARDUINOJSON_ENABLE_STD_STREAM) && defined(__has_include)
#if __has_include(<istream>) && \ #if __has_include(<istream>) && \
__has_include(<ostream>) && \ __has_include(<ostream>) && \
!defined(min) && \ !defined(min) && \
!defined(max) !defined(max)
#define ARDUINOJSON_ENABLE_STD_STREAM 1 #define ARDUINOJSON_ENABLE_STD_STREAM 1
#else #else
#define ARDUINOJSON_ENABLE_STD_STREAM 0 #define ARDUINOJSON_ENABLE_STD_STREAM 0
#endif #endif
#endif #endif
// Auto enable std::string if the right header is here and no conflicting // Auto enable std::string if the right header is here and no conflicting
// macro is defined // macro is defined
#if !defined(ARDUINOJSON_ENABLE_STD_STRING) && defined(__has_include) #if !defined(ARDUINOJSON_ENABLE_STD_STRING) && defined(__has_include)
#if __has_include(<string>) && !defined(min) && !defined(max) #if __has_include(<string>) && !defined(min) && !defined(max)
#define ARDUINOJSON_ENABLE_STD_STRING 1 #define ARDUINOJSON_ENABLE_STD_STRING 1
#else #else
#define ARDUINOJSON_ENABLE_STD_STRING 0 #define ARDUINOJSON_ENABLE_STD_STRING 0
#endif #endif
#endif #endif
#if ARDUINOJSON_EMBEDDED_MODE #if ARDUINOJSON_EMBEDDED_MODE
// Store floats by default to reduce the memory usage (issue #134) // Store floats by default to reduce the memory usage (issue #134)
#ifndef ARDUINOJSON_USE_DOUBLE #ifndef ARDUINOJSON_USE_DOUBLE
#define ARDUINOJSON_USE_DOUBLE 0 #define ARDUINOJSON_USE_DOUBLE 0
#endif #endif
// Store longs by default, because they usually match the size of a float. // Store longs by default, because they usually match the size of a float.
#ifndef ARDUINOJSON_USE_LONG_LONG #ifndef ARDUINOJSON_USE_LONG_LONG
#define ARDUINOJSON_USE_LONG_LONG 0 #define ARDUINOJSON_USE_LONG_LONG 0
#endif #endif
// Embedded systems usually don't have std::string // Embedded systems usually don't have std::string
#ifndef ARDUINOJSON_ENABLE_STD_STRING #ifndef ARDUINOJSON_ENABLE_STD_STRING
#define ARDUINOJSON_ENABLE_STD_STRING 0 #define ARDUINOJSON_ENABLE_STD_STRING 0
#endif #endif
// Embedded systems usually don't have std::stream // Embedded systems usually don't have std::stream
#ifndef ARDUINOJSON_ENABLE_STD_STREAM #ifndef ARDUINOJSON_ENABLE_STD_STREAM
#define ARDUINOJSON_ENABLE_STD_STREAM 0 #define ARDUINOJSON_ENABLE_STD_STREAM 0
#endif #endif
// Limit nesting as the stack is likely to be small // Limit nesting as the stack is likely to be small
#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT #ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10 #define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10
#endif #endif
#else // ARDUINOJSON_EMBEDDED_MODE #else // ARDUINOJSON_EMBEDDED_MODE
// On a computer we have plenty of memory so we can use doubles // On a computer we have plenty of memory so we can use doubles
#ifndef ARDUINOJSON_USE_DOUBLE #ifndef ARDUINOJSON_USE_DOUBLE
#define ARDUINOJSON_USE_DOUBLE 1 #define ARDUINOJSON_USE_DOUBLE 1
#endif #endif
// Use long long when available // Use long long when available
#ifndef ARDUINOJSON_USE_LONG_LONG #ifndef ARDUINOJSON_USE_LONG_LONG
#if ARDUINOJSON_HAS_LONG_LONG || ARDUINOJSON_HAS_INT64 #if ARDUINOJSON_HAS_LONG_LONG || ARDUINOJSON_HAS_INT64
#define ARDUINOJSON_USE_LONG_LONG 1 #define ARDUINOJSON_USE_LONG_LONG 1
#else #else
#define ARDUINOJSON_USE_LONG_LONG 0 #define ARDUINOJSON_USE_LONG_LONG 0
#endif #endif
#endif #endif
// On a computer, we can use std::string // On a computer, we can use std::string
#ifndef ARDUINOJSON_ENABLE_STD_STRING #ifndef ARDUINOJSON_ENABLE_STD_STRING
#define ARDUINOJSON_ENABLE_STD_STRING 1 #define ARDUINOJSON_ENABLE_STD_STRING 1
#endif #endif
// On a computer, we can assume std::stream // On a computer, we can assume std::stream
#ifndef ARDUINOJSON_ENABLE_STD_STREAM #ifndef ARDUINOJSON_ENABLE_STD_STREAM
#define ARDUINOJSON_ENABLE_STD_STREAM 1 #define ARDUINOJSON_ENABLE_STD_STREAM 1
#endif #endif
// On a computer, the stack is large so we can increase nesting limit // On a computer, the stack is large so we can increase nesting limit
#ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT #ifndef ARDUINOJSON_DEFAULT_NESTING_LIMIT
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50 #define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50
#endif #endif
#endif // ARDUINOJSON_EMBEDDED_MODE #endif // ARDUINOJSON_EMBEDDED_MODE
#ifdef ARDUINO #ifdef ARDUINO
#include <Arduino.h> #include <Arduino.h>
// Enable support for Arduino's String class // Enable support for Arduino's String class
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING #ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 1 #define ARDUINOJSON_ENABLE_ARDUINO_STRING 1
#endif #endif
// Enable support for Arduino's Stream class // Enable support for Arduino's Stream class
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM #ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1 #define ARDUINOJSON_ENABLE_ARDUINO_STREAM 1
#endif #endif
// Enable support for Arduino's Print class // Enable support for Arduino's Print class
#ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT #ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT
#define ARDUINOJSON_ENABLE_ARDUINO_PRINT 1 #define ARDUINOJSON_ENABLE_ARDUINO_PRINT 1
#endif #endif
#else // ARDUINO #else // ARDUINO
// Disable support for Arduino's String class // Disable support for Arduino's String class
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING #ifndef ARDUINOJSON_ENABLE_ARDUINO_STRING
#define ARDUINOJSON_ENABLE_ARDUINO_STRING 0 #define ARDUINOJSON_ENABLE_ARDUINO_STRING 0
#endif #endif
// Disable support for Arduino's Stream class // Disable support for Arduino's Stream class
#ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM #ifndef ARDUINOJSON_ENABLE_ARDUINO_STREAM
#define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0 #define ARDUINOJSON_ENABLE_ARDUINO_STREAM 0
#endif #endif
// Disable support for Arduino's Print class // Disable support for Arduino's Print class
#ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT #ifndef ARDUINOJSON_ENABLE_ARDUINO_PRINT
#define ARDUINOJSON_ENABLE_ARDUINO_PRINT 0 #define ARDUINOJSON_ENABLE_ARDUINO_PRINT 0
#endif #endif
#endif // ARDUINO #endif // ARDUINO
#ifndef ARDUINOJSON_ENABLE_PROGMEM #ifndef ARDUINOJSON_ENABLE_PROGMEM
#ifdef PROGMEM #ifdef PROGMEM
#define ARDUINOJSON_ENABLE_PROGMEM 1 #define ARDUINOJSON_ENABLE_PROGMEM 1
#else #else
#define ARDUINOJSON_ENABLE_PROGMEM 0 #define ARDUINOJSON_ENABLE_PROGMEM 0
#endif #endif
#endif #endif
// Convert unicode escape sequence (\u0123) to UTF-8 // Convert unicode escape sequence (\u0123) to UTF-8
#ifndef ARDUINOJSON_DECODE_UNICODE #ifndef ARDUINOJSON_DECODE_UNICODE
#define ARDUINOJSON_DECODE_UNICODE 1 #define ARDUINOJSON_DECODE_UNICODE 1
#endif #endif
// Ignore comments in input // Ignore comments in input
#ifndef ARDUINOJSON_ENABLE_COMMENTS #ifndef ARDUINOJSON_ENABLE_COMMENTS
#define ARDUINOJSON_ENABLE_COMMENTS 0 #define ARDUINOJSON_ENABLE_COMMENTS 0
#endif #endif
// Support NaN in JSON // Support NaN in JSON
#ifndef ARDUINOJSON_ENABLE_NAN #ifndef ARDUINOJSON_ENABLE_NAN
#define ARDUINOJSON_ENABLE_NAN 0 #define ARDUINOJSON_ENABLE_NAN 0
#endif #endif
// Support Infinity in JSON // Support Infinity in JSON
#ifndef ARDUINOJSON_ENABLE_INFINITY #ifndef ARDUINOJSON_ENABLE_INFINITY
#define ARDUINOJSON_ENABLE_INFINITY 0 #define ARDUINOJSON_ENABLE_INFINITY 0
#endif #endif
// Control the exponentiation threshold for big numbers // Control the exponentiation threshold for big numbers
// CAUTION: cannot be more that 1e9 !!!! // CAUTION: cannot be more that 1e9 !!!!
#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD #ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD
#define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7 #define ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD 1e7
#endif #endif
// Control the exponentiation threshold for small numbers // Control the exponentiation threshold for small numbers
#ifndef ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD #ifndef ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD
#define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5 #define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5
#endif #endif
#ifndef ARDUINOJSON_LITTLE_ENDIAN #ifndef ARDUINOJSON_LITTLE_ENDIAN
#if defined(_MSC_VER) || \ #if defined(_MSC_VER) || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \ (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
defined(__LITTLE_ENDIAN__) || defined(__i386) || defined(__x86_64) defined(__LITTLE_ENDIAN__) || defined(__i386) || defined(__x86_64)
#define ARDUINOJSON_LITTLE_ENDIAN 1 #define ARDUINOJSON_LITTLE_ENDIAN 1
#else #else
#define ARDUINOJSON_LITTLE_ENDIAN 0 #define ARDUINOJSON_LITTLE_ENDIAN 0
#endif #endif
#endif #endif
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT #ifndef ARDUINOJSON_ENABLE_ALIGNMENT
#if defined(__AVR) #if defined(__AVR)
#define ARDUINOJSON_ENABLE_ALIGNMENT 0 #define ARDUINOJSON_ENABLE_ALIGNMENT 0
#else #else
#define ARDUINOJSON_ENABLE_ALIGNMENT 1 #define ARDUINOJSON_ENABLE_ALIGNMENT 1
#endif #endif
#endif #endif
#ifndef ARDUINOJSON_TAB #ifndef ARDUINOJSON_TAB
#define ARDUINOJSON_TAB " " #define ARDUINOJSON_TAB " "
#endif #endif
#ifndef ARDUINOJSON_ENABLE_STRING_DEDUPLICATION #ifndef ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
#define ARDUINOJSON_ENABLE_STRING_DEDUPLICATION 1 #define ARDUINOJSON_ENABLE_STRING_DEDUPLICATION 1
#endif #endif
#ifndef ARDUINOJSON_STRING_BUFFER_SIZE #ifndef ARDUINOJSON_STRING_BUFFER_SIZE
#define ARDUINOJSON_STRING_BUFFER_SIZE 32 #define ARDUINOJSON_STRING_BUFFER_SIZE 32
#endif #endif
#ifndef ARDUINOJSON_DEBUG #ifndef ARDUINOJSON_DEBUG
#ifdef __PLATFORMIO_BUILD_DEBUG__ #ifdef __PLATFORMIO_BUILD_DEBUG__
#define ARDUINOJSON_DEBUG 1 #define ARDUINOJSON_DEBUG 1
#else #else
#define ARDUINOJSON_DEBUG 0 #define ARDUINOJSON_DEBUG 0
#endif #endif
#endif #endif
#if ARDUINOJSON_HAS_NULLPTR && defined(nullptr)
#error nullptr is defined as a macro. Remove the faulty #define or #undef nullptr
// See https://github.com/bblanchon/ArduinoJson/issues/1355
#endif

View File

@@ -1,115 +1,125 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
#include <ArduinoJson/Polyfills/preprocessor.hpp>
#if ARDUINOJSON_ENABLE_STD_STREAM #include <ArduinoJson/Polyfills/static_array.hpp>
#include <ostream>
#endif #if ARDUINOJSON_ENABLE_STD_STREAM
#include <ostream>
namespace ARDUINOJSON_NAMESPACE { #endif
class DeserializationError { namespace ARDUINOJSON_NAMESPACE {
// safe bool idiom
typedef void (DeserializationError::*bool_type)() const; class DeserializationError {
void safeBoolHelper() const {} // safe bool idiom
typedef void (DeserializationError::*bool_type)() const;
public: void safeBoolHelper() const {}
enum Code {
Ok, public:
IncompleteInput, enum Code {
InvalidInput, Ok,
NoMemory, EmptyInput,
NotSupported, IncompleteInput,
TooDeep InvalidInput,
}; NoMemory,
NotSupported,
DeserializationError() {} TooDeep
DeserializationError(Code c) : _code(c) {} };
// Compare with DeserializationError DeserializationError() {}
friend bool operator==(const DeserializationError& lhs, DeserializationError(Code c) : _code(c) {}
const DeserializationError& rhs) {
return lhs._code == rhs._code; // Compare with DeserializationError
} friend bool operator==(const DeserializationError& lhs,
friend bool operator!=(const DeserializationError& lhs, const DeserializationError& rhs) {
const DeserializationError& rhs) { return lhs._code == rhs._code;
return lhs._code != rhs._code; }
} friend bool operator!=(const DeserializationError& lhs,
const DeserializationError& rhs) {
// Compare with Code return lhs._code != rhs._code;
friend bool operator==(const DeserializationError& lhs, Code rhs) { }
return lhs._code == rhs;
} // Compare with Code
friend bool operator==(Code lhs, const DeserializationError& rhs) { friend bool operator==(const DeserializationError& lhs, Code rhs) {
return lhs == rhs._code; return lhs._code == rhs;
} }
friend bool operator!=(const DeserializationError& lhs, Code rhs) { friend bool operator==(Code lhs, const DeserializationError& rhs) {
return lhs._code != rhs; return lhs == rhs._code;
} }
friend bool operator!=(Code lhs, const DeserializationError& rhs) { friend bool operator!=(const DeserializationError& lhs, Code rhs) {
return lhs != rhs._code; return lhs._code != rhs;
} }
friend bool operator!=(Code lhs, const DeserializationError& rhs) {
// Behaves like a bool return lhs != rhs._code;
operator bool_type() const { }
return _code != Ok ? &DeserializationError::safeBoolHelper : 0;
} // Behaves like a bool
friend bool operator==(bool value, const DeserializationError& err) { operator bool_type() const {
return static_cast<bool>(err) == value; return _code != Ok ? &DeserializationError::safeBoolHelper : 0;
} }
friend bool operator==(const DeserializationError& err, bool value) { friend bool operator==(bool value, const DeserializationError& err) {
return static_cast<bool>(err) == value; return static_cast<bool>(err) == value;
} }
friend bool operator!=(bool value, const DeserializationError& err) { friend bool operator==(const DeserializationError& err, bool value) {
return static_cast<bool>(err) != value; return static_cast<bool>(err) == value;
} }
friend bool operator!=(const DeserializationError& err, bool value) { friend bool operator!=(bool value, const DeserializationError& err) {
return static_cast<bool>(err) != value; return static_cast<bool>(err) != value;
} }
friend bool operator!=(const DeserializationError& err, bool value) {
// Returns internal enum, useful for switch statement return static_cast<bool>(err) != value;
Code code() const { }
return _code;
} // Returns internal enum, useful for switch statement
Code code() const {
const char* c_str() const { return _code;
switch (_code) { }
case Ok:
return "Ok"; const char* c_str() const {
case TooDeep: static const char* messages[] = {
return "TooDeep"; "Ok", "EmptyInput", "IncompleteInput", "InvalidInput",
case NoMemory: "NoMemory", "NotSupported", "TooDeep"};
return "NoMemory"; ARDUINOJSON_ASSERT(static_cast<size_t>(_code) <
case InvalidInput: sizeof(messages) / sizeof(messages[0]));
return "InvalidInput"; return messages[_code];
case IncompleteInput: }
return "IncompleteInput";
case NotSupported: #if ARDUINOJSON_ENABLE_PROGMEM
return "NotSupported"; const __FlashStringHelper* f_str() const {
default: ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s0, "Ok");
return "???"; 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");
private: ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s5, "NotSupported");
Code _code; ARDUINOJSON_DEFINE_STATIC_ARRAY(char, s6, "TooDeep");
}; ARDUINOJSON_DEFINE_STATIC_ARRAY(
const char*, messages,
#if ARDUINOJSON_ENABLE_STD_STREAM ARDUINOJSON_EXPAND7({s0, s1, s2, s3, s4, s5, s6}));
inline std::ostream& operator<<(std::ostream& s, return ARDUINOJSON_READ_STATIC_ARRAY(const __FlashStringHelper*, messages,
const DeserializationError& e) { _code);
s << e.c_str(); }
return s; #endif
}
private:
inline std::ostream& operator<<(std::ostream& s, DeserializationError::Code c) { Code _code;
s << DeserializationError(c).c_str(); };
return s;
} #if ARDUINOJSON_ENABLE_STD_STREAM
#endif inline std::ostream& operator<<(std::ostream& s,
const DeserializationError& e) {
} // namespace ARDUINOJSON_NAMESPACE s << e.c_str();
return s;
}
inline std::ostream& operator<<(std::ostream& s, DeserializationError::Code c) {
s << DeserializationError(c).c_str();
return s;
}
#endif
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,66 +1,66 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
class Filter { class Filter {
public: public:
explicit Filter(VariantConstRef v) : _variant(v) {} explicit Filter(VariantConstRef v) : _variant(v) {}
bool allow() const { bool allow() const {
return _variant; return _variant;
} }
bool allowArray() const { bool allowArray() const {
return _variant == true || _variant.is<ArrayRef>(); return _variant == true || _variant.is<ArrayRef>();
} }
bool allowObject() const { bool allowObject() const {
return _variant == true || _variant.is<ObjectRef>(); return _variant == true || _variant.is<ObjectRef>();
} }
bool allowValue() const { bool allowValue() const {
return _variant == true; return _variant == true;
} }
template <typename TKey> template <typename TKey>
Filter operator[](const TKey& key) const { Filter operator[](const TKey& key) const {
if (_variant == true) // "true" means "allow recursively" if (_variant == true) // "true" means "allow recursively"
return *this; return *this;
else else
return Filter(_variant[key]); return Filter(_variant[key] | _variant["*"]);
} }
private: private:
VariantConstRef _variant; VariantConstRef _variant;
}; };
struct AllowAllFilter { struct AllowAllFilter {
bool allow() const { bool allow() const {
return true; return true;
} }
bool allowArray() const { bool allowArray() const {
return true; return true;
} }
bool allowObject() const { bool allowObject() const {
return true; return true;
} }
bool allowValue() const { bool allowValue() const {
return true; return true;
} }
template <typename TKey> template <typename TKey>
AllowAllFilter operator[](const TKey&) const { AllowAllFilter operator[](const TKey&) const {
return AllowAllFilter(); return AllowAllFilter();
} }
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,29 +1,29 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
#include <ArduinoJson/Polyfills/assert.hpp> #include <ArduinoJson/Polyfills/assert.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
class NestingLimit { class NestingLimit {
public: public:
NestingLimit() : _value(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {} NestingLimit() : _value(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
explicit NestingLimit(uint8_t n) : _value(n) {} explicit NestingLimit(uint8_t n) : _value(n) {}
NestingLimit decrement() const { NestingLimit decrement() const {
ARDUINOJSON_ASSERT(_value > 0); ARDUINOJSON_ASSERT(_value > 0);
return NestingLimit(static_cast<uint8_t>(_value - 1)); return NestingLimit(static_cast<uint8_t>(_value - 1));
} }
bool reached() const { bool reached() const {
return _value == 0; return _value == 0;
} }
private: private:
uint8_t _value; uint8_t _value;
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,56 +1,56 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
#include <stdlib.h> // for size_t #include <stdlib.h> // for size_t
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
// The default reader is a simple wrapper for Readers that are not copiable // The default reader is a simple wrapper for Readers that are not copiable
template <typename TSource, typename Enable = void> template <typename TSource, typename Enable = void>
struct Reader { struct Reader {
public: public:
Reader(TSource& source) : _source(&source) {} Reader(TSource& source) : _source(&source) {}
int read() { int read() {
return _source->read(); return _source->read();
} }
size_t readBytes(char* buffer, size_t length) { size_t readBytes(char* buffer, size_t length) {
return _source->readBytes(buffer, length); return _source->readBytes(buffer, length);
} }
private: private:
TSource* _source; TSource* _source;
}; };
template <typename TSource, typename Enable = void> template <typename TSource, typename Enable = void>
struct BoundedReader { struct BoundedReader {
// no default implementation because we need to pass the size to the // no default implementation because we need to pass the size to the
// constructor // constructor
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE
#include <ArduinoJson/Deserialization/Readers/IteratorReader.hpp> #include <ArduinoJson/Deserialization/Readers/IteratorReader.hpp>
#include <ArduinoJson/Deserialization/Readers/RamReader.hpp> #include <ArduinoJson/Deserialization/Readers/RamReader.hpp>
#include <ArduinoJson/Deserialization/Readers/VariantReader.hpp> #include <ArduinoJson/Deserialization/Readers/VariantReader.hpp>
#if ARDUINOJSON_ENABLE_ARDUINO_STREAM #if ARDUINOJSON_ENABLE_ARDUINO_STREAM
#include <ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp> #include <ArduinoJson/Deserialization/Readers/ArduinoStreamReader.hpp>
#endif #endif
#if ARDUINOJSON_ENABLE_ARDUINO_STRING #if ARDUINOJSON_ENABLE_ARDUINO_STRING
#include <ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp> #include <ArduinoJson/Deserialization/Readers/ArduinoStringReader.hpp>
#endif #endif
#if ARDUINOJSON_ENABLE_PROGMEM #if ARDUINOJSON_ENABLE_PROGMEM
#include <ArduinoJson/Deserialization/Readers/FlashReader.hpp> #include <ArduinoJson/Deserialization/Readers/FlashReader.hpp>
#endif #endif
#if ARDUINOJSON_ENABLE_STD_STREAM #if ARDUINOJSON_ENABLE_STD_STREAM
#include <ArduinoJson/Deserialization/Readers/StdStreamReader.hpp> #include <ArduinoJson/Deserialization/Readers/StdStreamReader.hpp>
#endif #endif

View File

@@ -1,31 +1,31 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <Stream.h> #include <Arduino.h>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename TSource> template <typename TSource>
struct Reader<TSource, struct Reader<TSource,
typename enable_if<is_base_of<Stream, TSource>::value>::type> { typename enable_if<is_base_of<Stream, TSource>::value>::type> {
public: public:
explicit Reader(Stream& stream) : _stream(&stream) {} explicit Reader(Stream& stream) : _stream(&stream) {}
int read() { int read() {
// don't use _stream.read() as it ignores the timeout // don't use _stream.read() as it ignores the timeout
char c; char c;
return _stream->readBytes(&c, 1) ? static_cast<unsigned char>(c) : -1; return _stream->readBytes(&c, 1) ? static_cast<unsigned char>(c) : -1;
} }
size_t readBytes(char* buffer, size_t length) { size_t readBytes(char* buffer, size_t length) {
return _stream->readBytes(buffer, length); return _stream->readBytes(buffer, length);
} }
private: private:
Stream* _stream; Stream* _stream;
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,17 +1,17 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename TSource> template <typename TSource>
struct Reader<TSource, struct Reader<TSource,
typename enable_if<is_base_of< ::String, TSource>::value>::type> typename enable_if<is_base_of< ::String, TSource>::value>::type>
: BoundedReader<const char*> { : BoundedReader<const char*> {
explicit Reader(const ::String& s) explicit Reader(const ::String& s)
: BoundedReader<const char*>(s.c_str(), s.length()) {} : BoundedReader<const char*>(s.c_str(), s.length()) {}
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,53 +1,53 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <> template <>
struct Reader<const __FlashStringHelper*, void> { struct Reader<const __FlashStringHelper*, void> {
const char* _ptr; const char* _ptr;
public: public:
explicit Reader(const __FlashStringHelper* ptr) explicit Reader(const __FlashStringHelper* ptr)
: _ptr(reinterpret_cast<const char*>(ptr)) {} : _ptr(reinterpret_cast<const char*>(ptr)) {}
int read() { int read() {
return pgm_read_byte(_ptr++); return pgm_read_byte(_ptr++);
} }
size_t readBytes(char* buffer, size_t length) { size_t readBytes(char* buffer, size_t length) {
memcpy_P(buffer, _ptr, length); memcpy_P(buffer, _ptr, length);
_ptr += length; _ptr += length;
return length; return length;
} }
}; };
template <> template <>
struct BoundedReader<const __FlashStringHelper*, void> { struct BoundedReader<const __FlashStringHelper*, void> {
const char* _ptr; const char* _ptr;
const char* _end; const char* _end;
public: public:
explicit BoundedReader(const __FlashStringHelper* ptr, size_t size) explicit BoundedReader(const __FlashStringHelper* ptr, size_t size)
: _ptr(reinterpret_cast<const char*>(ptr)), _end(_ptr + size) {} : _ptr(reinterpret_cast<const char*>(ptr)), _end(_ptr + size) {}
int read() { int read() {
if (_ptr < _end) if (_ptr < _end)
return pgm_read_byte(_ptr++); return pgm_read_byte(_ptr++);
else else
return -1; return -1;
} }
size_t readBytes(char* buffer, size_t length) { size_t readBytes(char* buffer, size_t length) {
size_t available = static_cast<size_t>(_end - _ptr); size_t available = static_cast<size_t>(_end - _ptr);
if (available < length) if (available < length)
length = available; length = available;
memcpy_P(buffer, _ptr, length); memcpy_P(buffer, _ptr, length);
_ptr += length; _ptr += length;
return length; return length;
} }
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,43 +1,43 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename TIterator> template <typename TIterator>
class IteratorReader { class IteratorReader {
TIterator _ptr, _end; TIterator _ptr, _end;
public: public:
explicit IteratorReader(TIterator begin, TIterator end) explicit IteratorReader(TIterator begin, TIterator end)
: _ptr(begin), _end(end) {} : _ptr(begin), _end(end) {}
int read() { int read() {
if (_ptr < _end) if (_ptr < _end)
return static_cast<unsigned char>(*_ptr++); return static_cast<unsigned char>(*_ptr++);
else else
return -1; return -1;
} }
size_t readBytes(char* buffer, size_t length) { size_t readBytes(char* buffer, size_t length) {
size_t i = 0; size_t i = 0;
while (i < length && _ptr < _end) buffer[i++] = *_ptr++; while (i < length && _ptr < _end) buffer[i++] = *_ptr++;
return i; return i;
} }
}; };
template <typename T> template <typename T>
struct void_ { struct void_ {
typedef void type; typedef void type;
}; };
template <typename TSource> template <typename TSource>
struct Reader<TSource, typename void_<typename TSource::const_iterator>::type> struct Reader<TSource, typename void_<typename TSource::const_iterator>::type>
: IteratorReader<typename TSource::const_iterator> { : IteratorReader<typename TSource::const_iterator> {
explicit Reader(const TSource& source) explicit Reader(const TSource& source)
: IteratorReader<typename TSource::const_iterator>(source.begin(), : IteratorReader<typename TSource::const_iterator>(source.begin(),
source.end()) {} source.end()) {}
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,50 +1,50 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Polyfills/type_traits.hpp> #include <ArduinoJson/Polyfills/type_traits.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename T> template <typename T>
struct IsCharOrVoid { struct IsCharOrVoid {
static const bool value = static const bool value =
is_same<T, void>::value || is_same<T, char>::value || is_same<T, void>::value || is_same<T, char>::value ||
is_same<T, unsigned char>::value || is_same<T, signed char>::value; is_same<T, unsigned char>::value || is_same<T, signed char>::value;
}; };
template <typename T> template <typename T>
struct IsCharOrVoid<const T> : IsCharOrVoid<T> {}; struct IsCharOrVoid<const T> : IsCharOrVoid<T> {};
template <typename TSource> template <typename TSource>
struct Reader<TSource*, struct Reader<TSource*,
typename enable_if<IsCharOrVoid<TSource>::value>::type> { typename enable_if<IsCharOrVoid<TSource>::value>::type> {
const char* _ptr; const char* _ptr;
public: public:
explicit Reader(const void* ptr) explicit Reader(const void* ptr)
: _ptr(ptr ? reinterpret_cast<const char*>(ptr) : "") {} : _ptr(ptr ? reinterpret_cast<const char*>(ptr) : "") {}
int read() { int read() {
return static_cast<unsigned char>(*_ptr++); return static_cast<unsigned char>(*_ptr++);
} }
size_t readBytes(char* buffer, size_t length) { size_t readBytes(char* buffer, size_t length) {
for (size_t i = 0; i < length; i++) buffer[i] = *_ptr++; for (size_t i = 0; i < length; i++) buffer[i] = *_ptr++;
return length; return length;
} }
}; };
template <typename TSource> template <typename TSource>
struct BoundedReader<TSource*, struct BoundedReader<TSource*,
typename enable_if<IsCharOrVoid<TSource>::value>::type> typename enable_if<IsCharOrVoid<TSource>::value>::type>
: public IteratorReader<const char*> { : public IteratorReader<const char*> {
public: public:
explicit BoundedReader(const void* ptr, size_t len) explicit BoundedReader(const void* ptr, size_t len)
: IteratorReader<const char*>(reinterpret_cast<const char*>(ptr), : IteratorReader<const char*>(reinterpret_cast<const char*>(ptr),
reinterpret_cast<const char*>(ptr) + len) {} reinterpret_cast<const char*>(ptr) + len) {}
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,29 +1,29 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <istream> #include <istream>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename TSource> template <typename TSource>
struct Reader<TSource, typename enable_if< struct Reader<TSource, typename enable_if<
is_base_of<std::istream, TSource>::value>::type> { is_base_of<std::istream, TSource>::value>::type> {
public: public:
explicit Reader(std::istream& stream) : _stream(&stream) {} explicit Reader(std::istream& stream) : _stream(&stream) {}
int read() { int read() {
return _stream->get(); return _stream->get();
} }
size_t readBytes(char* buffer, size_t length) { size_t readBytes(char* buffer, size_t length) {
_stream->read(buffer, static_cast<std::streamsize>(length)); _stream->read(buffer, static_cast<std::streamsize>(length));
return static_cast<size_t>(_stream->gcount()); return static_cast<size_t>(_stream->gcount());
} }
private: private:
std::istream* _stream; std::istream* _stream;
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,34 +1,34 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Object/MemberProxy.hpp> #include <ArduinoJson/Object/MemberProxy.hpp>
#include <ArduinoJson/Variant/VariantRef.hpp> #include <ArduinoJson/Variant/VariantRef.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename TArray> template <typename TArray>
struct Reader<ElementProxy<TArray>, void> : Reader<char*, void> { struct Reader<ElementProxy<TArray>, void> : Reader<char*, void> {
explicit Reader(const ElementProxy<TArray>& x) explicit Reader(const ElementProxy<TArray>& x)
: Reader<char*, void>(x.template as<const char*>()) {} : Reader<char*, void>(x.template as<const char*>()) {}
}; };
template <typename TObject, typename TStringRef> template <typename TObject, typename TStringRef>
struct Reader<MemberProxy<TObject, TStringRef>, void> : Reader<char*, void> { struct Reader<MemberProxy<TObject, TStringRef>, void> : Reader<char*, void> {
explicit Reader(const MemberProxy<TObject, TStringRef>& x) explicit Reader(const MemberProxy<TObject, TStringRef>& x)
: Reader<char*, void>(x.template as<const char*>()) {} : Reader<char*, void>(x.template as<const char*>()) {}
}; };
template <> template <>
struct Reader<VariantRef, void> : Reader<char*, void> { struct Reader<VariantRef, void> : Reader<char*, void> {
explicit Reader(VariantRef x) : Reader<char*, void>(x.as<const char*>()) {} explicit Reader(VariantRef x) : Reader<char*, void>(x.as<const char*>()) {}
}; };
template <> template <>
struct Reader<VariantConstRef, void> : Reader<char*, void> { struct Reader<VariantConstRef, void> : Reader<char*, void> {
explicit Reader(VariantConstRef x) explicit Reader(VariantConstRef x)
: Reader<char*, void>(x.as<const char*>()) {} : Reader<char*, void>(x.as<const char*>()) {}
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,68 +1,71 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Deserialization/DeserializationError.hpp> #include <ArduinoJson/Deserialization/DeserializationError.hpp>
#include <ArduinoJson/Deserialization/Filter.hpp> #include <ArduinoJson/Deserialization/Filter.hpp>
#include <ArduinoJson/Deserialization/NestingLimit.hpp> #include <ArduinoJson/Deserialization/NestingLimit.hpp>
#include <ArduinoJson/Deserialization/Reader.hpp> #include <ArduinoJson/Deserialization/Reader.hpp>
#include <ArduinoJson/StringStorage/StringStorage.hpp> #include <ArduinoJson/StringStorage/StringStorage.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <template <typename, typename> class TDeserializer, typename TReader, template <template <typename, typename> class TDeserializer, typename TReader,
typename TWriter> typename TWriter>
TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool, TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool,
TReader reader, TReader reader,
TWriter writer) { TWriter writer) {
return TDeserializer<TReader, TWriter>(pool, reader, writer); return TDeserializer<TReader, TWriter>(pool, reader, writer);
} }
// deserialize(JsonDocument&, const std::string&, NestingLimit, Filter); // deserialize(JsonDocument&, const std::string&, NestingLimit, Filter);
// deserialize(JsonDocument&, const String&, NestingLimit, Filter); // deserialize(JsonDocument&, const String&, NestingLimit, Filter);
// deserialize(JsonDocument&, char*, NestingLimit, Filter); // deserialize(JsonDocument&, char*, NestingLimit, Filter);
// deserialize(JsonDocument&, const char*, NestingLimit, Filter); // deserialize(JsonDocument&, const char*, NestingLimit, Filter);
// deserialize(JsonDocument&, const __FlashStringHelper*, NestingLimit, Filter); // deserialize(JsonDocument&, const __FlashStringHelper*, NestingLimit, Filter);
template <template <typename, typename> class TDeserializer, typename TString, template <template <typename, typename> class TDeserializer, typename TString,
typename TFilter> typename TFilter>
typename enable_if<!is_array<TString>::value, DeserializationError>::type typename enable_if<!is_array<TString>::value, DeserializationError>::type
deserialize(JsonDocument &doc, const TString &input, NestingLimit nestingLimit, deserialize(JsonDocument &doc, const TString &input, NestingLimit nestingLimit,
TFilter filter) { TFilter filter) {
Reader<TString> reader(input); Reader<TString> reader(input);
doc.clear(); doc.clear();
return makeDeserializer<TDeserializer>(doc.memoryPool(), reader, return makeDeserializer<TDeserializer>(
makeStringStorage(input)) doc.memoryPool(), reader,
.parse(doc.data(), filter, nestingLimit); makeStringStorage(input, doc.memoryPool()))
} .parse(doc.data(), filter, nestingLimit);
// }
// deserialize(JsonDocument&, char*, size_t, NestingLimit, Filter); //
// deserialize(JsonDocument&, const char*, size_t, NestingLimit, Filter); // deserialize(JsonDocument&, char*, size_t, NestingLimit, Filter);
// deserialize(JsonDocument&, const __FlashStringHelper*, size_t, NL, Filter); // deserialize(JsonDocument&, const char*, size_t, NestingLimit, Filter);
template <template <typename, typename> class TDeserializer, typename TChar, // deserialize(JsonDocument&, const __FlashStringHelper*, size_t, NL, Filter);
typename TFilter> template <template <typename, typename> class TDeserializer, typename TChar,
DeserializationError deserialize(JsonDocument &doc, TChar *input, typename TFilter>
size_t inputSize, NestingLimit nestingLimit, DeserializationError deserialize(JsonDocument &doc, TChar *input,
TFilter filter) { size_t inputSize, NestingLimit nestingLimit,
BoundedReader<TChar *> reader(input, inputSize); TFilter filter) {
doc.clear(); BoundedReader<TChar *> reader(input, inputSize);
return makeDeserializer<TDeserializer>(doc.memoryPool(), reader, doc.clear();
makeStringStorage(input)) return makeDeserializer<TDeserializer>(
.parse(doc.data(), filter, nestingLimit); doc.memoryPool(), reader,
} makeStringStorage(input, doc.memoryPool()))
// .parse(doc.data(), filter, nestingLimit);
// deserialize(JsonDocument&, std::istream&, NestingLimit, Filter); }
// deserialize(JsonDocument&, Stream&, NestingLimit, Filter); //
template <template <typename, typename> class TDeserializer, typename TStream, // deserialize(JsonDocument&, std::istream&, NestingLimit, Filter);
typename TFilter> // deserialize(JsonDocument&, Stream&, NestingLimit, Filter);
DeserializationError deserialize(JsonDocument &doc, TStream &input, template <template <typename, typename> class TDeserializer, typename TStream,
NestingLimit nestingLimit, TFilter filter) { typename TFilter>
Reader<TStream> reader(input); DeserializationError deserialize(JsonDocument &doc, TStream &input,
doc.clear(); NestingLimit nestingLimit, TFilter filter) {
return makeDeserializer<TDeserializer>(doc.memoryPool(), reader, Reader<TStream> reader(input);
makeStringStorage(input)) doc.clear();
.parse(doc.data(), filter, nestingLimit); return makeDeserializer<TDeserializer>(
} doc.memoryPool(), reader,
makeStringStorage(input, doc.memoryPool()))
} // namespace ARDUINOJSON_NAMESPACE .parse(doc.data(), filter, nestingLimit);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,164 +1,164 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Document/JsonDocument.hpp> #include <ArduinoJson/Document/JsonDocument.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
// Helper to implement the "base-from-member" idiom // Helper to implement the "base-from-member" idiom
// (we need to store the allocator before constructing JsonDocument) // (we need to store the allocator before constructing JsonDocument)
template <typename TAllocator> template <typename TAllocator>
class AllocatorOwner { class AllocatorOwner {
public: public:
AllocatorOwner() {} AllocatorOwner() {}
AllocatorOwner(const AllocatorOwner& src) : _allocator(src._allocator) {} AllocatorOwner(const AllocatorOwner& src) : _allocator(src._allocator) {}
AllocatorOwner(TAllocator a) : _allocator(a) {} AllocatorOwner(TAllocator a) : _allocator(a) {}
void* allocate(size_t size) { void* allocate(size_t size) {
return _allocator.allocate(size); return _allocator.allocate(size);
} }
void deallocate(void* ptr) { void deallocate(void* ptr) {
if (ptr) if (ptr)
_allocator.deallocate(ptr); _allocator.deallocate(ptr);
} }
void* reallocate(void* ptr, size_t new_size) { void* reallocate(void* ptr, size_t new_size) {
return _allocator.reallocate(ptr, new_size); return _allocator.reallocate(ptr, new_size);
} }
TAllocator& allocator() { TAllocator& allocator() {
return _allocator; return _allocator;
} }
private: private:
TAllocator _allocator; TAllocator _allocator;
}; };
template <typename TAllocator> template <typename TAllocator>
class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument { class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
public: public:
explicit BasicJsonDocument(size_t capa, TAllocator alloc = TAllocator()) explicit BasicJsonDocument(size_t capa, TAllocator alloc = TAllocator())
: AllocatorOwner<TAllocator>(alloc), JsonDocument(allocPool(capa)) {} : AllocatorOwner<TAllocator>(alloc), JsonDocument(allocPool(capa)) {}
// Copy-constructor // Copy-constructor
BasicJsonDocument(const BasicJsonDocument& src) BasicJsonDocument(const BasicJsonDocument& src)
: AllocatorOwner<TAllocator>(src), JsonDocument() { : AllocatorOwner<TAllocator>(src), JsonDocument() {
copyAssignFrom(src); copyAssignFrom(src);
} }
// Move-constructor // Move-constructor
#if ARDUINOJSON_HAS_RVALUE_REFERENCES #if ARDUINOJSON_HAS_RVALUE_REFERENCES
BasicJsonDocument(BasicJsonDocument&& src) : AllocatorOwner<TAllocator>(src) { BasicJsonDocument(BasicJsonDocument&& src) : AllocatorOwner<TAllocator>(src) {
moveAssignFrom(src); moveAssignFrom(src);
} }
#endif #endif
BasicJsonDocument(const JsonDocument& src) { BasicJsonDocument(const JsonDocument& src) {
copyAssignFrom(src); copyAssignFrom(src);
} }
// Construct from variant, array, or object // Construct from variant, array, or object
template <typename T> template <typename T>
BasicJsonDocument( BasicJsonDocument(
const T& src, const T& src,
typename enable_if< typename enable_if<
is_same<T, VariantRef>::value || is_same<T, VariantConstRef>::value || is_same<T, VariantRef>::value || is_same<T, VariantConstRef>::value ||
is_same<T, ArrayRef>::value || is_same<T, ArrayConstRef>::value || is_same<T, ArrayRef>::value || is_same<T, ArrayConstRef>::value ||
is_same<T, ObjectRef>::value || is_same<T, ObjectRef>::value ||
is_same<T, ObjectConstRef>::value>::type* = 0) is_same<T, ObjectConstRef>::value>::type* = 0)
: JsonDocument(allocPool(src.memoryUsage())) { : JsonDocument(allocPool(src.memoryUsage())) {
set(src); set(src);
} }
// disambiguate // disambiguate
BasicJsonDocument(VariantRef src) BasicJsonDocument(VariantRef src)
: JsonDocument(allocPool(src.memoryUsage())) { : JsonDocument(allocPool(src.memoryUsage())) {
set(src); set(src);
} }
~BasicJsonDocument() { ~BasicJsonDocument() {
freePool(); freePool();
} }
BasicJsonDocument& operator=(const BasicJsonDocument& src) { BasicJsonDocument& operator=(const BasicJsonDocument& src) {
copyAssignFrom(src); copyAssignFrom(src);
return *this; return *this;
} }
#if ARDUINOJSON_HAS_RVALUE_REFERENCES #if ARDUINOJSON_HAS_RVALUE_REFERENCES
BasicJsonDocument& operator=(BasicJsonDocument&& src) { BasicJsonDocument& operator=(BasicJsonDocument&& src) {
moveAssignFrom(src); moveAssignFrom(src);
return *this; return *this;
} }
#endif #endif
template <typename T> template <typename T>
BasicJsonDocument& operator=(const T& src) { BasicJsonDocument& operator=(const T& src) {
reallocPoolIfTooSmall(src.memoryUsage()); reallocPoolIfTooSmall(src.memoryUsage());
set(src); set(src);
return *this; return *this;
} }
void shrinkToFit() { void shrinkToFit() {
ptrdiff_t bytes_reclaimed = _pool.squash(); ptrdiff_t bytes_reclaimed = _pool.squash();
if (bytes_reclaimed == 0) if (bytes_reclaimed == 0)
return; return;
void* old_ptr = _pool.buffer(); void* old_ptr = _pool.buffer();
void* new_ptr = this->reallocate(old_ptr, _pool.capacity()); void* new_ptr = this->reallocate(old_ptr, _pool.capacity());
ptrdiff_t ptr_offset = ptrdiff_t ptr_offset =
static_cast<char*>(new_ptr) - static_cast<char*>(old_ptr); static_cast<char*>(new_ptr) - static_cast<char*>(old_ptr);
_pool.movePointers(ptr_offset); _pool.movePointers(ptr_offset);
_data.movePointers(ptr_offset, ptr_offset - bytes_reclaimed); _data.movePointers(ptr_offset, ptr_offset - bytes_reclaimed);
} }
bool garbageCollect() { bool garbageCollect() {
// make a temporary clone and move assign // make a temporary clone and move assign
BasicJsonDocument tmp(*this); BasicJsonDocument tmp(*this);
if (!tmp.capacity()) if (!tmp.capacity())
return false; return false;
tmp.set(*this); tmp.set(*this);
moveAssignFrom(tmp); moveAssignFrom(tmp);
return true; return true;
} }
using AllocatorOwner<TAllocator>::allocator; using AllocatorOwner<TAllocator>::allocator;
private: private:
MemoryPool allocPool(size_t requiredSize) { MemoryPool allocPool(size_t requiredSize) {
size_t capa = addPadding(requiredSize); size_t capa = addPadding(requiredSize);
return MemoryPool(reinterpret_cast<char*>(this->allocate(capa)), capa); return MemoryPool(reinterpret_cast<char*>(this->allocate(capa)), capa);
} }
void reallocPoolIfTooSmall(size_t requiredSize) { void reallocPoolIfTooSmall(size_t requiredSize) {
if (requiredSize <= capacity()) if (requiredSize <= capacity())
return; return;
freePool(); freePool();
replacePool(allocPool(addPadding(requiredSize))); replacePool(allocPool(addPadding(requiredSize)));
} }
void freePool() { void freePool() {
this->deallocate(memoryPool().buffer()); this->deallocate(memoryPool().buffer());
} }
void copyAssignFrom(const JsonDocument& src) { void copyAssignFrom(const JsonDocument& src) {
reallocPoolIfTooSmall(src.capacity()); reallocPoolIfTooSmall(src.capacity());
set(src); set(src);
} }
void moveAssignFrom(BasicJsonDocument& src) { void moveAssignFrom(BasicJsonDocument& src) {
freePool(); freePool();
_data = src._data; _data = src._data;
_pool = src._pool; _pool = src._pool;
src._data.setNull(); src._data.setNull();
src._pool = MemoryPool(0, 0); src._pool = MemoryPool(0, 0);
} }
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,29 +1,29 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Document/BasicJsonDocument.hpp> #include <ArduinoJson/Document/BasicJsonDocument.hpp>
#include <stdlib.h> // malloc, free #include <stdlib.h> // malloc, free
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
struct DefaultAllocator { struct DefaultAllocator {
void* allocate(size_t size) { void* allocate(size_t size) {
return malloc(size); return malloc(size);
} }
void deallocate(void* ptr) { void deallocate(void* ptr) {
free(ptr); free(ptr);
} }
void* reallocate(void* ptr, size_t new_size) { void* reallocate(void* ptr, size_t new_size) {
return realloc(ptr, new_size); return realloc(ptr, new_size);
} }
}; };
typedef BasicJsonDocument<DefaultAllocator> DynamicJsonDocument; typedef BasicJsonDocument<DefaultAllocator> DynamicJsonDocument;
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,328 +1,333 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Array/ElementProxy.hpp> #include <ArduinoJson/Array/ElementProxy.hpp>
#include <ArduinoJson/Memory/MemoryPool.hpp> #include <ArduinoJson/Memory/MemoryPool.hpp>
#include <ArduinoJson/Object/MemberProxy.hpp> #include <ArduinoJson/Object/MemberProxy.hpp>
#include <ArduinoJson/Object/ObjectRef.hpp> #include <ArduinoJson/Object/ObjectRef.hpp>
#include <ArduinoJson/Variant/VariantRef.hpp> #include <ArduinoJson/Variant/VariantRef.hpp>
#include <ArduinoJson/Variant/VariantTo.hpp> #include <ArduinoJson/Variant/VariantTo.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
class JsonDocument : public Visitable { class JsonDocument : public Visitable {
public: public:
template <typename Visitor> template <typename TVisitor>
void accept(Visitor& visitor) const { typename TVisitor::result_type accept(TVisitor& visitor) const {
return getVariant().accept(visitor); return getVariant().accept(visitor);
} }
template <typename T> template <typename T>
typename VariantAs<T>::type as() { typename VariantAs<T>::type as() {
return getVariant().template as<T>(); return getVariant().template as<T>();
} }
template <typename T> template <typename T>
typename VariantConstAs<T>::type as() const { typename VariantConstAs<T>::type as() const {
return getVariant().template as<T>(); return getVariant().template as<T>();
} }
void clear() { void clear() {
_pool.clear(); _pool.clear();
_data.setNull(); _data.setNull();
} }
template <typename T> template <typename T>
bool is() const { bool is() const {
return getVariant().template is<T>(); return getVariant().template is<T>();
} }
bool isNull() const { bool isNull() const {
return getVariant().isNull(); return getVariant().isNull();
} }
size_t memoryUsage() const { size_t memoryUsage() const {
return _pool.size(); return _pool.size();
} }
size_t nesting() const { bool overflowed() const {
return _data.nesting(); return _pool.overflowed();
} }
size_t capacity() const { size_t nesting() const {
return _pool.capacity(); return _data.nesting();
} }
size_t size() const { size_t capacity() const {
return _data.size(); return _pool.capacity();
} }
bool set(const JsonDocument& src) { size_t size() const {
return to<VariantRef>().set(src.as<VariantRef>()); return _data.size();
} }
template <typename T> bool set(const JsonDocument& src) {
typename enable_if<!is_base_of<JsonDocument, T>::value, bool>::type set( return to<VariantRef>().set(src.as<VariantRef>());
const T& src) { }
return to<VariantRef>().set(src);
} template <typename T>
typename enable_if<!is_base_of<JsonDocument, T>::value, bool>::type set(
template <typename T> const T& src) {
typename VariantTo<T>::type to() { return to<VariantRef>().set(src);
clear(); }
return getVariant().template to<T>();
} template <typename T>
typename VariantTo<T>::type to() {
// for internal use only clear();
MemoryPool& memoryPool() { return getVariant().template to<T>();
return _pool; }
}
// for internal use only
VariantData& data() { MemoryPool& memoryPool() {
return _data; return _pool;
} }
ArrayRef createNestedArray() { // for internal use only
return addElement().to<ArrayRef>(); VariantData& data() {
} return _data;
}
// createNestedArray(char*)
// createNestedArray(const char*) ArrayRef createNestedArray() {
// createNestedArray(const __FlashStringHelper*) return addElement().to<ArrayRef>();
template <typename TChar> }
ArrayRef createNestedArray(TChar* key) {
return getOrAddMember(key).template to<ArrayRef>(); // createNestedArray(char*)
} // createNestedArray(const char*)
// createNestedArray(const __FlashStringHelper*)
// createNestedArray(const std::string&) template <typename TChar>
// createNestedArray(const String&) ArrayRef createNestedArray(TChar* key) {
template <typename TString> return getOrAddMember(key).template to<ArrayRef>();
ArrayRef createNestedArray(const TString& key) { }
return getOrAddMember(key).template to<ArrayRef>();
} // createNestedArray(const std::string&)
// createNestedArray(const String&)
ObjectRef createNestedObject() { template <typename TString>
return addElement().to<ObjectRef>(); ArrayRef createNestedArray(const TString& key) {
} return getOrAddMember(key).template to<ArrayRef>();
}
// createNestedObject(char*)
// createNestedObject(const char*) ObjectRef createNestedObject() {
// createNestedObject(const __FlashStringHelper*) return addElement().to<ObjectRef>();
template <typename TChar> }
ObjectRef createNestedObject(TChar* key) {
return getOrAddMember(key).template to<ObjectRef>(); // createNestedObject(char*)
} // createNestedObject(const char*)
// createNestedObject(const __FlashStringHelper*)
// createNestedObject(const std::string&) template <typename TChar>
// createNestedObject(const String&) ObjectRef createNestedObject(TChar* key) {
template <typename TString> return getOrAddMember(key).template to<ObjectRef>();
ObjectRef createNestedObject(const TString& key) { }
return getOrAddMember(key).template to<ObjectRef>();
} // createNestedObject(const std::string&)
// createNestedObject(const String&)
// containsKey(char*) const template <typename TString>
// containsKey(const char*) const ObjectRef createNestedObject(const TString& key) {
// containsKey(const __FlashStringHelper*) const return getOrAddMember(key).template to<ObjectRef>();
template <typename TChar> }
bool containsKey(TChar* key) const {
return !getMember(key).isUndefined(); // containsKey(char*) const
} // containsKey(const char*) const
// containsKey(const __FlashStringHelper*) const
// containsKey(const std::string&) const template <typename TChar>
// containsKey(const String&) const bool containsKey(TChar* key) const {
template <typename TString> return !getMember(key).isUndefined();
bool containsKey(const TString& key) const { }
return !getMember(key).isUndefined();
} // containsKey(const std::string&) const
// containsKey(const String&) const
// operator[](const std::string&) template <typename TString>
// operator[](const String&) bool containsKey(const TString& key) const {
template <typename TString> return !getMember(key).isUndefined();
FORCE_INLINE typename enable_if<IsString<TString>::value, }
MemberProxy<JsonDocument&, TString> >::type
operator[](const TString& key) { // operator[](const std::string&)
return MemberProxy<JsonDocument&, TString>(*this, key); // operator[](const String&)
} template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value,
// operator[](char*) MemberProxy<JsonDocument&, TString> >::type
// operator[](const char*) operator[](const TString& key) {
// operator[](const __FlashStringHelper*) return MemberProxy<JsonDocument&, TString>(*this, key);
template <typename TChar> }
FORCE_INLINE typename enable_if<IsString<TChar*>::value,
MemberProxy<JsonDocument&, TChar*> >::type // operator[](char*)
operator[](TChar* key) { // operator[](const char*)
return MemberProxy<JsonDocument&, TChar*>(*this, key); // operator[](const __FlashStringHelper*)
} template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value,
// operator[](const std::string&) const MemberProxy<JsonDocument&, TChar*> >::type
// operator[](const String&) const operator[](TChar* key) {
template <typename TString> return MemberProxy<JsonDocument&, TChar*>(*this, key);
FORCE_INLINE }
typename enable_if<IsString<TString>::value, VariantConstRef>::type
operator[](const TString& key) const { // operator[](const std::string&) const
return getMember(key); // operator[](const String&) const
} template <typename TString>
FORCE_INLINE
// operator[](char*) const typename enable_if<IsString<TString>::value, VariantConstRef>::type
// operator[](const char*) const operator[](const TString& key) const {
// operator[](const __FlashStringHelper*) const return getMember(key);
template <typename TChar> }
FORCE_INLINE
typename enable_if<IsString<TChar*>::value, VariantConstRef>::type // operator[](char*) const
operator[](TChar* key) const { // operator[](const char*) const
return getMember(key); // operator[](const __FlashStringHelper*) const
} template <typename TChar>
FORCE_INLINE
FORCE_INLINE ElementProxy<JsonDocument&> operator[](size_t index) { typename enable_if<IsString<TChar*>::value, VariantConstRef>::type
return ElementProxy<JsonDocument&>(*this, index); operator[](TChar* key) const {
} return getMember(key);
}
FORCE_INLINE VariantConstRef operator[](size_t index) const {
return getElement(index); FORCE_INLINE ElementProxy<JsonDocument&> operator[](size_t index) {
} return ElementProxy<JsonDocument&>(*this, index);
}
FORCE_INLINE VariantRef getElement(size_t index) {
return VariantRef(&_pool, _data.getElement(index)); FORCE_INLINE VariantConstRef operator[](size_t index) const {
} return getElement(index);
}
FORCE_INLINE VariantConstRef getElement(size_t index) const {
return VariantConstRef(_data.getElement(index)); FORCE_INLINE VariantRef getElement(size_t index) {
} return VariantRef(&_pool, _data.getElement(index));
}
FORCE_INLINE VariantRef getOrAddElement(size_t index) {
return VariantRef(&_pool, _data.getOrAddElement(index, &_pool)); FORCE_INLINE VariantConstRef getElement(size_t index) const {
} return VariantConstRef(_data.getElement(index));
}
// JsonVariantConst getMember(char*) const
// JsonVariantConst getMember(const char*) const FORCE_INLINE VariantRef getOrAddElement(size_t index) {
// JsonVariantConst getMember(const __FlashStringHelper*) const return VariantRef(&_pool, _data.getOrAddElement(index, &_pool));
template <typename TChar> }
FORCE_INLINE VariantConstRef getMember(TChar* key) const {
return VariantConstRef(_data.getMember(adaptString(key))); // JsonVariantConst getMember(char*) const
} // JsonVariantConst getMember(const char*) const
// JsonVariantConst getMember(const __FlashStringHelper*) const
// JsonVariantConst getMember(const std::string&) const template <typename TChar>
// JsonVariantConst getMember(const String&) const FORCE_INLINE VariantConstRef getMember(TChar* key) const {
template <typename TString> return VariantConstRef(_data.getMember(adaptString(key)));
FORCE_INLINE }
typename enable_if<IsString<TString>::value, VariantConstRef>::type
getMember(const TString& key) const { // JsonVariantConst getMember(const std::string&) const
return VariantConstRef(_data.getMember(adaptString(key))); // JsonVariantConst getMember(const String&) const
} template <typename TString>
FORCE_INLINE
// JsonVariant getMember(char*) typename enable_if<IsString<TString>::value, VariantConstRef>::type
// JsonVariant getMember(const char*) getMember(const TString& key) const {
// JsonVariant getMember(const __FlashStringHelper*) return VariantConstRef(_data.getMember(adaptString(key)));
template <typename TChar> }
FORCE_INLINE VariantRef getMember(TChar* key) {
return VariantRef(&_pool, _data.getMember(adaptString(key))); // JsonVariant getMember(char*)
} // JsonVariant getMember(const char*)
// JsonVariant getMember(const __FlashStringHelper*)
// JsonVariant getMember(const std::string&) template <typename TChar>
// JsonVariant getMember(const String&) FORCE_INLINE VariantRef getMember(TChar* key) {
template <typename TString> return VariantRef(&_pool, _data.getMember(adaptString(key)));
FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type }
getMember(const TString& key) {
return VariantRef(&_pool, _data.getMember(adaptString(key))); // JsonVariant getMember(const std::string&)
} // JsonVariant getMember(const String&)
template <typename TString>
// getOrAddMember(char*) FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type
// getOrAddMember(const char*) getMember(const TString& key) {
// getOrAddMember(const __FlashStringHelper*) return VariantRef(&_pool, _data.getMember(adaptString(key)));
template <typename TChar> }
FORCE_INLINE VariantRef getOrAddMember(TChar* key) {
return VariantRef(&_pool, _data.getOrAddMember(adaptString(key), &_pool)); // getOrAddMember(char*)
} // getOrAddMember(const char*)
// getOrAddMember(const __FlashStringHelper*)
// getOrAddMember(const std::string&) template <typename TChar>
// getOrAddMember(const String&) FORCE_INLINE VariantRef getOrAddMember(TChar* key) {
template <typename TString> return VariantRef(&_pool, _data.getOrAddMember(adaptString(key), &_pool));
FORCE_INLINE VariantRef getOrAddMember(const TString& key) { }
return VariantRef(&_pool, _data.getOrAddMember(adaptString(key), &_pool));
} // getOrAddMember(const std::string&)
// getOrAddMember(const String&)
FORCE_INLINE VariantRef addElement() { template <typename TString>
return VariantRef(&_pool, _data.addElement(&_pool)); FORCE_INLINE VariantRef getOrAddMember(const TString& key) {
} return VariantRef(&_pool, _data.getOrAddMember(adaptString(key), &_pool));
}
template <typename TValue>
FORCE_INLINE bool add(const TValue& value) { FORCE_INLINE VariantRef addElement() {
return addElement().set(value); return VariantRef(&_pool, _data.addElement(&_pool));
} }
// add(char*) const template <typename TValue>
// add(const char*) const FORCE_INLINE bool add(const TValue& value) {
// add(const __FlashStringHelper*) const return addElement().set(value);
template <typename TChar> }
FORCE_INLINE bool add(TChar* value) {
return addElement().set(value); // add(char*) const
} // add(const char*) const
// add(const __FlashStringHelper*) const
FORCE_INLINE void remove(size_t index) { template <typename TChar>
_data.remove(index); FORCE_INLINE bool add(TChar* value) {
} return addElement().set(value);
// remove(char*) }
// remove(const char*)
// remove(const __FlashStringHelper*) FORCE_INLINE void remove(size_t index) {
template <typename TChar> _data.remove(index);
FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove( }
TChar* key) { // remove(char*)
_data.remove(adaptString(key)); // remove(const char*)
} // remove(const __FlashStringHelper*)
// remove(const std::string&) template <typename TChar>
// remove(const String&) FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove(
template <typename TString> TChar* key) {
FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove( _data.remove(adaptString(key));
const TString& key) { }
_data.remove(adaptString(key)); // remove(const std::string&)
} // remove(const String&)
template <typename TString>
FORCE_INLINE operator VariantConstRef() const { FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
return VariantConstRef(&_data); const TString& key) {
} _data.remove(adaptString(key));
}
bool operator==(VariantConstRef rhs) const {
return getVariant() == rhs; FORCE_INLINE operator VariantConstRef() const {
} return VariantConstRef(&_data);
}
bool operator!=(VariantConstRef rhs) const {
return getVariant() != rhs; bool operator==(VariantConstRef rhs) const {
} return getVariant() == rhs;
}
protected:
JsonDocument() : _pool(0, 0) { bool operator!=(VariantConstRef rhs) const {
_data.setNull(); return getVariant() != rhs;
} }
JsonDocument(MemoryPool pool) : _pool(pool) { protected:
_data.setNull(); JsonDocument() : _pool(0, 0) {
} _data.setNull();
}
JsonDocument(char* buf, size_t capa) : _pool(buf, capa) {
_data.setNull(); JsonDocument(MemoryPool pool) : _pool(pool) {
} _data.setNull();
}
void replacePool(MemoryPool pool) {
_pool = pool; JsonDocument(char* buf, size_t capa) : _pool(buf, capa) {
} _data.setNull();
}
VariantRef getVariant() {
return VariantRef(&_pool, &_data); void replacePool(MemoryPool pool) {
} _pool = pool;
}
VariantConstRef getVariant() const {
return VariantConstRef(&_data); VariantRef getVariant() {
} return VariantRef(&_pool, &_data);
}
MemoryPool _pool;
VariantData _data; VariantConstRef getVariant() const {
return VariantConstRef(&_data);
private: }
JsonDocument(const JsonDocument&);
JsonDocument& operator=(const JsonDocument&); MemoryPool _pool;
}; VariantData _data;
} // namespace ARDUINOJSON_NAMESPACE private:
JsonDocument(const JsonDocument&);
JsonDocument& operator=(const JsonDocument&);
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,56 +1,56 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Document/JsonDocument.hpp> #include <ArduinoJson/Document/JsonDocument.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <size_t desiredCapacity> template <size_t desiredCapacity>
class StaticJsonDocument : public JsonDocument { class StaticJsonDocument : public JsonDocument {
static const size_t _capacity = static const size_t _capacity =
AddPadding<Max<1, desiredCapacity>::value>::value; AddPadding<Max<1, desiredCapacity>::value>::value;
public: public:
StaticJsonDocument() : JsonDocument(_buffer, _capacity) {} StaticJsonDocument() : JsonDocument(_buffer, _capacity) {}
StaticJsonDocument(const StaticJsonDocument& src) StaticJsonDocument(const StaticJsonDocument& src)
: JsonDocument(_buffer, _capacity) { : JsonDocument(_buffer, _capacity) {
set(src); set(src);
} }
template <typename T> template <typename T>
StaticJsonDocument(const T& src, StaticJsonDocument(const T& src,
typename enable_if<IsVisitable<T>::value>::type* = 0) typename enable_if<IsVisitable<T>::value>::type* = 0)
: JsonDocument(_buffer, _capacity) { : JsonDocument(_buffer, _capacity) {
set(src); set(src);
} }
// disambiguate // disambiguate
StaticJsonDocument(VariantRef src) : JsonDocument(_buffer, _capacity) { StaticJsonDocument(VariantRef src) : JsonDocument(_buffer, _capacity) {
set(src); set(src);
} }
StaticJsonDocument operator=(const StaticJsonDocument& src) { StaticJsonDocument operator=(const StaticJsonDocument& src) {
set(src); set(src);
return *this; return *this;
} }
template <typename T> template <typename T>
StaticJsonDocument operator=(const T& src) { StaticJsonDocument operator=(const T& src) {
set(src); set(src);
return *this; return *this;
} }
void garbageCollect() { void garbageCollect() {
StaticJsonDocument tmp(*this); StaticJsonDocument tmp(*this);
set(tmp); set(tmp);
} }
private: private:
char _buffer[_capacity]; char _buffer[_capacity];
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,39 +1,39 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
class EscapeSequence { class EscapeSequence {
public: public:
// Optimized for code size on a 8-bit AVR // Optimized for code size on a 8-bit AVR
static char escapeChar(char c) { static char escapeChar(char c) {
const char *p = escapeTable(true); const char *p = escapeTable(true);
while (p[0] && p[1] != c) { while (p[0] && p[1] != c) {
p += 2; p += 2;
} }
return p[0]; return p[0];
} }
// Optimized for code size on a 8-bit AVR // Optimized for code size on a 8-bit AVR
static char unescapeChar(char c) { static char unescapeChar(char c) {
const char *p = escapeTable(false); const char *p = escapeTable(false);
for (;;) { for (;;) {
if (p[0] == '\0') if (p[0] == '\0')
return 0; return 0;
if (p[0] == c) if (p[0] == c)
return p[1]; return p[1];
p += 2; p += 2;
} }
} }
private: private:
static const char *escapeTable(bool excludeSolidus) { static const char *escapeTable(bool excludeSolidus) {
return &"//\"\"\\\\b\bf\fn\nr\rt\t"[excludeSolidus ? 2 : 0]; return &"//\"\"\\\\b\bf\fn\nr\rt\t"[excludeSolidus ? 2 : 0];
} }
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

File diff suppressed because it is too large Load Diff

View File

@@ -1,126 +1,135 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Json/TextFormatter.hpp> #include <ArduinoJson/Json/TextFormatter.hpp>
#include <ArduinoJson/Misc/Visitable.hpp> #include <ArduinoJson/Misc/Visitable.hpp>
#include <ArduinoJson/Serialization/measure.hpp> #include <ArduinoJson/Serialization/measure.hpp>
#include <ArduinoJson/Serialization/serialize.hpp> #include <ArduinoJson/Serialization/serialize.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename TWriter> template <typename TWriter>
class JsonSerializer { class JsonSerializer : public Visitor<size_t> {
public: public:
JsonSerializer(TWriter writer) : _formatter(writer) {} JsonSerializer(TWriter writer) : _formatter(writer) {}
FORCE_INLINE void visitArray(const CollectionData &array) { FORCE_INLINE size_t visitArray(const CollectionData &array) {
write('['); write('[');
VariantSlot *slot = array.head(); VariantSlot *slot = array.head();
while (slot != 0) { while (slot != 0) {
slot->data()->accept(*this); slot->data()->accept(*this);
slot = slot->next(); slot = slot->next();
if (slot == 0) if (slot == 0)
break; break;
write(','); write(',');
} }
write(']'); write(']');
} return bytesWritten();
}
void visitObject(const CollectionData &object) {
write('{'); size_t visitObject(const CollectionData &object) {
write('{');
VariantSlot *slot = object.head();
VariantSlot *slot = object.head();
while (slot != 0) {
_formatter.writeString(slot->key()); while (slot != 0) {
write(':'); _formatter.writeString(slot->key());
slot->data()->accept(*this); write(':');
slot->data()->accept(*this);
slot = slot->next();
if (slot == 0) slot = slot->next();
break; if (slot == 0)
break;
write(',');
} write(',');
}
write('}');
} write('}');
return bytesWritten();
void visitFloat(Float value) { }
_formatter.writeFloat(value);
} size_t visitFloat(Float value) {
_formatter.writeFloat(value);
void visitString(const char *value) { return bytesWritten();
_formatter.writeString(value); }
}
size_t visitString(const char *value) {
void visitRawJson(const char *data, size_t n) { _formatter.writeString(value);
_formatter.writeRaw(data, n); return bytesWritten();
} }
void visitNegativeInteger(UInt value) { size_t visitRawJson(const char *data, size_t n) {
_formatter.writeNegativeInteger(value); _formatter.writeRaw(data, n);
} return bytesWritten();
}
void visitPositiveInteger(UInt value) {
_formatter.writePositiveInteger(value); size_t visitNegativeInteger(UInt value) {
} _formatter.writeNegativeInteger(value);
return bytesWritten();
void visitBoolean(bool value) { }
_formatter.writeBoolean(value);
} size_t visitPositiveInteger(UInt value) {
_formatter.writePositiveInteger(value);
void visitNull() { return bytesWritten();
_formatter.writeRaw("null"); }
}
size_t visitBoolean(bool value) {
size_t bytesWritten() const { _formatter.writeBoolean(value);
return _formatter.bytesWritten(); return bytesWritten();
} }
protected: size_t visitNull() {
void write(char c) { _formatter.writeRaw("null");
_formatter.writeRaw(c); return bytesWritten();
} }
void write(const char *s) { protected:
_formatter.writeRaw(s); size_t bytesWritten() const {
} return _formatter.bytesWritten();
}
private:
TextFormatter<TWriter> _formatter; void write(char c) {
}; _formatter.writeRaw(c);
}
template <typename TSource, typename TDestination>
size_t serializeJson(const TSource &source, TDestination &destination) { void write(const char *s) {
return serialize<JsonSerializer>(source, destination); _formatter.writeRaw(s);
} }
template <typename TSource> private:
size_t serializeJson(const TSource &source, void *buffer, size_t bufferSize) { TextFormatter<TWriter> _formatter;
return serialize<JsonSerializer>(source, buffer, bufferSize); };
}
template <typename TSource, typename TDestination>
template <typename TSource> size_t serializeJson(const TSource &source, TDestination &destination) {
size_t measureJson(const TSource &source) { return serialize<JsonSerializer>(source, destination);
return measure<JsonSerializer>(source); }
}
template <typename TSource>
#if ARDUINOJSON_ENABLE_STD_STREAM size_t serializeJson(const TSource &source, void *buffer, size_t bufferSize) {
template <typename T> return serialize<JsonSerializer>(source, buffer, bufferSize);
inline typename enable_if<IsVisitable<T>::value, std::ostream &>::type }
operator<<(std::ostream &os, const T &source) {
serializeJson(source, os); template <typename TSource>
return os; size_t measureJson(const TSource &source) {
} return measure<JsonSerializer>(source);
#endif }
} // namespace ARDUINOJSON_NAMESPACE #if ARDUINOJSON_ENABLE_STD_STREAM
template <typename T>
inline typename enable_if<IsVisitable<T>::value, std::ostream &>::type
operator<<(std::ostream &os, const T &source) {
serializeJson(source, os);
return os;
}
#endif
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,55 +1,55 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Polyfills/assert.hpp> #include <ArduinoJson/Polyfills/assert.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename TReader> template <typename TReader>
class Latch { class Latch {
public: public:
Latch(TReader reader) : _reader(reader), _loaded(false) { Latch(TReader reader) : _reader(reader), _loaded(false) {
#if ARDUINOJSON_DEBUG #if ARDUINOJSON_DEBUG
_ended = false; _ended = false;
#endif #endif
} }
void clear() { void clear() {
_loaded = false; _loaded = false;
} }
int last() const { int last() const {
return _current; return _current;
} }
FORCE_INLINE char current() { FORCE_INLINE char current() {
if (!_loaded) { if (!_loaded) {
load(); load();
} }
return _current; return _current;
} }
private: private:
void load() { void load() {
ARDUINOJSON_ASSERT(!_ended); ARDUINOJSON_ASSERT(!_ended);
int c = _reader.read(); int c = _reader.read();
#if ARDUINOJSON_DEBUG #if ARDUINOJSON_DEBUG
if (c <= 0) if (c <= 0)
_ended = true; _ended = true;
#endif #endif
_current = static_cast<char>(c > 0 ? c : 0); _current = static_cast<char>(c > 0 ? c : 0);
_loaded = true; _loaded = true;
} }
TReader _reader; TReader _reader;
char _current; char _current;
bool _loaded; bool _loaded;
#if ARDUINOJSON_DEBUG #if ARDUINOJSON_DEBUG
bool _ended; bool _ended;
#endif #endif
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,85 +1,89 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Configuration.hpp> #include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Json/JsonSerializer.hpp> #include <ArduinoJson/Json/JsonSerializer.hpp>
#include <ArduinoJson/Serialization/measure.hpp> #include <ArduinoJson/Serialization/measure.hpp>
#include <ArduinoJson/Serialization/serialize.hpp> #include <ArduinoJson/Serialization/serialize.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename TWriter> template <typename TWriter>
class PrettyJsonSerializer : public JsonSerializer<TWriter> { class PrettyJsonSerializer : public JsonSerializer<TWriter> {
typedef JsonSerializer<TWriter> base; typedef JsonSerializer<TWriter> base;
public: public:
PrettyJsonSerializer(TWriter &writer) : base(writer), _nesting(0) {} PrettyJsonSerializer(TWriter &writer) : base(writer), _nesting(0) {}
void visitArray(const CollectionData &array) { size_t visitArray(const CollectionData &array) {
VariantSlot *slot = array.head(); VariantSlot *slot = array.head();
if (!slot) if (slot) {
return base::write("[]"); base::write("[\r\n");
_nesting++;
base::write("[\r\n"); while (slot != 0) {
_nesting++; indent();
while (slot != 0) { slot->data()->accept(*this);
indent();
slot->data()->accept(*this); slot = slot->next();
base::write(slot ? ",\r\n" : "\r\n");
slot = slot->next(); }
base::write(slot ? ",\r\n" : "\r\n"); _nesting--;
} indent();
_nesting--; base::write("]");
indent(); } else {
base::write("]"); base::write("[]");
} }
return this->bytesWritten();
void visitObject(const CollectionData &object) { }
VariantSlot *slot = object.head();
if (!slot) size_t visitObject(const CollectionData &object) {
return base::write("{}"); VariantSlot *slot = object.head();
if (slot) {
base::write("{\r\n"); base::write("{\r\n");
_nesting++; _nesting++;
while (slot != 0) { while (slot != 0) {
indent(); indent();
base::visitString(slot->key()); base::visitString(slot->key());
base::write(": "); base::write(": ");
slot->data()->accept(*this); slot->data()->accept(*this);
slot = slot->next(); slot = slot->next();
base::write(slot ? ",\r\n" : "\r\n"); base::write(slot ? ",\r\n" : "\r\n");
} }
_nesting--; _nesting--;
indent(); indent();
base::write("}"); base::write("}");
} } else {
base::write("{}");
private: }
void indent() { return this->bytesWritten();
for (uint8_t i = 0; i < _nesting; i++) base::write(ARDUINOJSON_TAB); }
}
private:
uint8_t _nesting; void indent() {
}; for (uint8_t i = 0; i < _nesting; i++) base::write(ARDUINOJSON_TAB);
}
template <typename TSource, typename TDestination>
size_t serializeJsonPretty(const TSource &source, TDestination &destination) { uint8_t _nesting;
return serialize<PrettyJsonSerializer>(source, destination); };
}
template <typename TSource, typename TDestination>
template <typename TSource> size_t serializeJsonPretty(const TSource &source, TDestination &destination) {
size_t serializeJsonPretty(const TSource &source, void *buffer, return serialize<PrettyJsonSerializer>(source, destination);
size_t bufferSize) { }
return serialize<PrettyJsonSerializer>(source, buffer, bufferSize);
} template <typename TSource>
size_t serializeJsonPretty(const TSource &source, void *buffer,
template <typename TSource> size_t bufferSize) {
size_t measureJsonPretty(const TSource &source) { return serialize<PrettyJsonSerializer>(source, buffer, bufferSize);
return measure<PrettyJsonSerializer>(source); }
}
template <typename TSource>
} // namespace ARDUINOJSON_NAMESPACE size_t measureJsonPretty(const TSource &source) {
return measure<PrettyJsonSerializer>(source);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,158 +1,159 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <string.h> // for strlen #include <string.h> // for strlen
#include <ArduinoJson/Json/EscapeSequence.hpp> #include <ArduinoJson/Json/EscapeSequence.hpp>
#include <ArduinoJson/Numbers/FloatParts.hpp> #include <ArduinoJson/Numbers/FloatParts.hpp>
#include <ArduinoJson/Numbers/Integer.hpp> #include <ArduinoJson/Numbers/Integer.hpp>
#include <ArduinoJson/Polyfills/assert.hpp> #include <ArduinoJson/Polyfills/assert.hpp>
#include <ArduinoJson/Polyfills/attributes.hpp> #include <ArduinoJson/Polyfills/attributes.hpp>
#include <ArduinoJson/Serialization/CountingDecorator.hpp>
namespace ARDUINOJSON_NAMESPACE {
namespace ARDUINOJSON_NAMESPACE {
template <typename TWriter>
class TextFormatter { template <typename TWriter>
public: class TextFormatter {
explicit TextFormatter(TWriter writer) : _writer(writer), _length(0) {} public:
explicit TextFormatter(TWriter writer) : _writer(writer) {}
// Returns the number of bytes sent to the TWriter implementation.
size_t bytesWritten() const { // Returns the number of bytes sent to the TWriter implementation.
return _length; size_t bytesWritten() const {
} return _writer.count();
}
void writeBoolean(bool value) {
if (value) void writeBoolean(bool value) {
writeRaw("true"); if (value)
else writeRaw("true");
writeRaw("false"); else
} writeRaw("false");
}
void writeString(const char *value) {
ARDUINOJSON_ASSERT(value != NULL); void writeString(const char *value) {
writeRaw('\"'); ARDUINOJSON_ASSERT(value != NULL);
while (*value) writeChar(*value++); writeRaw('\"');
writeRaw('\"'); while (*value) writeChar(*value++);
} writeRaw('\"');
}
void writeChar(char c) {
char specialChar = EscapeSequence::escapeChar(c); void writeChar(char c) {
if (specialChar) { char specialChar = EscapeSequence::escapeChar(c);
writeRaw('\\'); if (specialChar) {
writeRaw(specialChar); writeRaw('\\');
} else { writeRaw(specialChar);
writeRaw(c); } else {
} writeRaw(c);
} }
}
template <typename T>
void writeFloat(T value) { template <typename T>
if (isnan(value)) void writeFloat(T value) {
return writeRaw(ARDUINOJSON_ENABLE_NAN ? "NaN" : "null"); if (isnan(value))
return writeRaw(ARDUINOJSON_ENABLE_NAN ? "NaN" : "null");
#if ARDUINOJSON_ENABLE_INFINITY
if (value < 0.0) { #if ARDUINOJSON_ENABLE_INFINITY
writeRaw('-'); if (value < 0.0) {
value = -value; writeRaw('-');
} value = -value;
}
if (isinf(value))
return writeRaw("Infinity"); if (isinf(value))
#else return writeRaw("Infinity");
if (isinf(value)) #else
return writeRaw("null"); if (isinf(value))
return writeRaw("null");
if (value < 0.0) {
writeRaw('-'); if (value < 0.0) {
value = -value; writeRaw('-');
} value = -value;
#endif }
#endif
FloatParts<T> parts(value);
FloatParts<T> parts(value);
writePositiveInteger(parts.integral);
if (parts.decimalPlaces) writePositiveInteger(parts.integral);
writeDecimals(parts.decimal, parts.decimalPlaces); if (parts.decimalPlaces)
writeDecimals(parts.decimal, parts.decimalPlaces);
if (parts.exponent < 0) {
writeRaw("e-"); if (parts.exponent < 0) {
writePositiveInteger(-parts.exponent); writeRaw("e-");
} writePositiveInteger(-parts.exponent);
}
if (parts.exponent > 0) {
writeRaw('e'); if (parts.exponent > 0) {
writePositiveInteger(parts.exponent); writeRaw('e');
} writePositiveInteger(parts.exponent);
} }
}
void writeNegativeInteger(UInt value) {
writeRaw('-'); void writeNegativeInteger(UInt value) {
writePositiveInteger(value); writeRaw('-');
} writePositiveInteger(value);
}
template <typename T>
void writePositiveInteger(T value) { template <typename T>
char buffer[22]; void writePositiveInteger(T value) {
char *end = buffer + sizeof(buffer); char buffer[22];
char *begin = end; char *end = buffer + sizeof(buffer);
char *begin = end;
// write the string in reverse order
do { // write the string in reverse order
*--begin = char(value % 10 + '0'); do {
value = T(value / 10); *--begin = char(value % 10 + '0');
} while (value); value = T(value / 10);
} while (value);
// and dump it in the right order
writeRaw(begin, end); // and dump it in the right order
} writeRaw(begin, end);
}
void writeDecimals(uint32_t value, int8_t width) {
// buffer should be big enough for all digits and the dot void writeDecimals(uint32_t value, int8_t width) {
char buffer[16]; // buffer should be big enough for all digits and the dot
char *end = buffer + sizeof(buffer); char buffer[16];
char *begin = end; char *end = buffer + sizeof(buffer);
char *begin = end;
// write the string in reverse order
while (width--) { // write the string in reverse order
*--begin = char(value % 10 + '0'); while (width--) {
value /= 10; *--begin = char(value % 10 + '0');
} value /= 10;
*--begin = '.'; }
*--begin = '.';
// and dump it in the right order
writeRaw(begin, end); // and dump it in the right order
} writeRaw(begin, end);
}
void writeRaw(const char *s) {
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), strlen(s)); void writeRaw(const char *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); void writeRaw(const char *s, size_t 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), void writeRaw(const char *begin, const char *end) {
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]) { template <size_t N>
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), N - 1); void writeRaw(const char (&s)[N]) {
} _writer.write(reinterpret_cast<const uint8_t *>(s), N - 1);
void writeRaw(char c) { }
_length += _writer.write(static_cast<uint8_t>(c)); void writeRaw(char c) {
} _writer.write(static_cast<uint8_t>(c));
}
protected:
TWriter _writer; protected:
size_t _length; CountingDecorator<TWriter> _writer;
size_t _length;
private:
TextFormatter &operator=(const TextFormatter &); // cannot be assigned private:
}; TextFormatter &operator=(const TextFormatter &); // cannot be assigned
} // namespace ARDUINOJSON_NAMESPACE };
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,67 +1,67 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
#include <stdint.h> // uint16_t, uint32_t #include <stdint.h> // uint16_t, uint32_t
// The high surrogate may be uninitialized if the pair is invalid, // The high surrogate may be uninitialized if the pair is invalid,
// we choose to ignore the problem to reduce the size of the code // we choose to ignore the problem to reduce the size of the code
// Garbage in => Garbage out // Garbage in => Garbage out
#if defined(__GNUC__) #if defined(__GNUC__)
#if __GNUC__ >= 7 #if __GNUC__ >= 7
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif #endif
#endif #endif
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
namespace Utf16 { namespace Utf16 {
inline bool isHighSurrogate(uint16_t codeunit) { inline bool isHighSurrogate(uint16_t codeunit) {
return codeunit >= 0xD800 && codeunit < 0xDC00; return codeunit >= 0xD800 && codeunit < 0xDC00;
} }
inline bool isLowSurrogate(uint16_t codeunit) { inline bool isLowSurrogate(uint16_t codeunit) {
return codeunit >= 0xDC00 && codeunit < 0xE000; return codeunit >= 0xDC00 && codeunit < 0xE000;
} }
class Codepoint { class Codepoint {
public: public:
Codepoint() : _highSurrogate(0) {} Codepoint() : _highSurrogate(0) {}
bool append(uint16_t codeunit) { bool append(uint16_t codeunit) {
if (isHighSurrogate(codeunit)) { if (isHighSurrogate(codeunit)) {
_highSurrogate = codeunit & 0x3FF; _highSurrogate = codeunit & 0x3FF;
return false; return false;
} }
if (isLowSurrogate(codeunit)) { if (isLowSurrogate(codeunit)) {
_codepoint = _codepoint =
uint32_t(0x10000 + ((_highSurrogate << 10) | (codeunit & 0x3FF))); uint32_t(0x10000 + ((_highSurrogate << 10) | (codeunit & 0x3FF)));
return true; return true;
} }
_codepoint = codeunit; _codepoint = codeunit;
return true; return true;
} }
uint32_t value() const { uint32_t value() const {
return _codepoint; return _codepoint;
} }
private: private:
uint16_t _highSurrogate; uint16_t _highSurrogate;
uint32_t _codepoint; uint32_t _codepoint;
}; };
} // namespace Utf16 } // namespace Utf16
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE
#if defined(__GNUC__) #if defined(__GNUC__)
#if __GNUC__ >= 8 #if __GNUC__ >= 8
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif
#endif #endif

View File

@@ -1,46 +1,46 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
namespace Utf8 { namespace Utf8 {
template <typename TStringBuilder> template <typename TStringBuilder>
inline void encodeCodepoint(uint32_t codepoint32, TStringBuilder& str) { inline void encodeCodepoint(uint32_t codepoint32, TStringBuilder& str) {
// this function was optimize for code size on AVR // this function was optimize for code size on AVR
// a buffer to store the string in reverse // a buffer to store the string in reverse
char buf[5]; char buf[5];
char* p = buf; char* p = buf;
*(p++) = 0; *(p++) = 0;
if (codepoint32 < 0x80) { if (codepoint32 < 0x80) {
*(p++) = char((codepoint32)); *(p++) = char((codepoint32));
} else { } else {
*(p++) = char((codepoint32 | 0x80) & 0xBF); *(p++) = char((codepoint32 | 0x80) & 0xBF);
uint16_t codepoint16 = uint16_t(codepoint32 >> 6); uint16_t codepoint16 = uint16_t(codepoint32 >> 6);
if (codepoint16 < 0x20) { // 0x800 if (codepoint16 < 0x20) { // 0x800
*(p++) = char(codepoint16 | 0xC0); *(p++) = char(codepoint16 | 0xC0);
} else { } else {
*(p++) = char((codepoint16 | 0x80) & 0xBF); *(p++) = char((codepoint16 | 0x80) & 0xBF);
codepoint16 = uint16_t(codepoint16 >> 6); codepoint16 = uint16_t(codepoint16 >> 6);
if (codepoint16 < 0x10) { // 0x10000 if (codepoint16 < 0x10) { // 0x10000
*(p++) = char(codepoint16 | 0xE0); *(p++) = char(codepoint16 | 0xE0);
} else { } else {
*(p++) = char((codepoint16 | 0x80) & 0xBF); *(p++) = char((codepoint16 | 0x80) & 0xBF);
codepoint16 = uint16_t(codepoint16 >> 6); codepoint16 = uint16_t(codepoint16 >> 6);
*(p++) = char(codepoint16 | 0xF0); *(p++) = char(codepoint16 | 0xF0);
} }
} }
} }
while (*(--p)) { while (*(--p)) {
str.append(*p); str.append(*p);
} }
} }
} // namespace Utf8 } // namespace Utf8
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,60 +1,60 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
#include <stddef.h> // size_t #include <stddef.h> // size_t
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
#if ARDUINOJSON_ENABLE_ALIGNMENT #if ARDUINOJSON_ENABLE_ALIGNMENT
inline bool isAligned(size_t value) { inline bool isAligned(size_t value) {
const size_t mask = sizeof(void *) - 1; const size_t mask = sizeof(void *) - 1;
size_t addr = value; size_t addr = value;
return (addr & mask) == 0; return (addr & mask) == 0;
} }
inline size_t addPadding(size_t bytes) { inline size_t addPadding(size_t bytes) {
const size_t mask = sizeof(void *) - 1; const size_t mask = sizeof(void *) - 1;
return (bytes + mask) & ~mask; return (bytes + mask) & ~mask;
} }
template <size_t bytes> template <size_t bytes>
struct AddPadding { struct AddPadding {
static const size_t mask = sizeof(void *) - 1; static const size_t mask = sizeof(void *) - 1;
static const size_t value = (bytes + mask) & ~mask; static const size_t value = (bytes + mask) & ~mask;
}; };
#else #else
inline bool isAligned(size_t) { inline bool isAligned(size_t) {
return true; return true;
} }
inline size_t addPadding(size_t bytes) { inline size_t addPadding(size_t bytes) {
return bytes; return bytes;
} }
template <size_t bytes> template <size_t bytes>
struct AddPadding { struct AddPadding {
static const size_t value = bytes; static const size_t value = bytes;
}; };
#endif #endif
template <typename T> template <typename T>
inline bool isAligned(T *ptr) { inline bool isAligned(T *ptr) {
return isAligned(reinterpret_cast<size_t>(ptr)); return isAligned(reinterpret_cast<size_t>(ptr));
} }
template <typename T> template <typename T>
inline T *addPadding(T *p) { inline T *addPadding(T *p) {
size_t address = addPadding(reinterpret_cast<size_t>(p)); size_t address = addPadding(reinterpret_cast<size_t>(p));
return reinterpret_cast<T *>(address); return reinterpret_cast<T *>(address);
} }
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,200 +1,212 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Memory/Alignment.hpp> #include <ArduinoJson/Memory/Alignment.hpp>
#include <ArduinoJson/Memory/StringSlot.hpp> #include <ArduinoJson/Polyfills/assert.hpp>
#include <ArduinoJson/Polyfills/assert.hpp> #include <ArduinoJson/Polyfills/mpl/max.hpp>
#include <ArduinoJson/Polyfills/mpl/max.hpp> #include <ArduinoJson/Variant/VariantSlot.hpp>
#include <ArduinoJson/Variant/VariantSlot.hpp>
#include <string.h> // memmove
#include <string.h> // memmove
#define JSON_STRING_SIZE(SIZE) (SIZE + 1)
namespace ARDUINOJSON_NAMESPACE {
namespace ARDUINOJSON_NAMESPACE {
// _begin _end
// v v // _begin _end
// +-------------+--------------+--------------+ // v v
// | strings... | (free) | ...variants | // +-------------+--------------+--------------+
// +-------------+--------------+--------------+ // | strings... | (free) | ...variants |
// ^ ^ // +-------------+--------------+--------------+
// _left _right // ^ ^
// _left _right
class MemoryPool {
public: class MemoryPool {
MemoryPool(char* buf, size_t capa) public:
: _begin(buf), MemoryPool(char* buf, size_t capa)
_left(buf), : _begin(buf),
_right(buf ? buf + capa : 0), _left(buf),
_end(buf ? buf + capa : 0) { _right(buf ? buf + capa : 0),
ARDUINOJSON_ASSERT(isAligned(_begin)); _end(buf ? buf + capa : 0),
ARDUINOJSON_ASSERT(isAligned(_right)); _overflowed(false) {
ARDUINOJSON_ASSERT(isAligned(_end)); ARDUINOJSON_ASSERT(isAligned(_begin));
} ARDUINOJSON_ASSERT(isAligned(_right));
ARDUINOJSON_ASSERT(isAligned(_end));
void* buffer() { }
return _begin;
} void* buffer() {
return _begin;
// Gets the capacity of the memoryPool in bytes }
size_t capacity() const {
return size_t(_end - _begin); // Gets the capacity of the memoryPool in bytes
} size_t capacity() const {
return size_t(_end - _begin);
size_t size() const { }
return size_t(_left - _begin + _end - _right);
} size_t size() const {
return size_t(_left - _begin + _end - _right);
VariantSlot* allocVariant() { }
return allocRight<VariantSlot>();
} bool overflowed() const {
return _overflowed;
template <typename TAdaptedString> }
const char* saveString(const TAdaptedString& str) {
if (str.isNull()) VariantSlot* allocVariant() {
return 0; return allocRight<VariantSlot>();
}
#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
const char* existingCopy = findString(str.begin()); template <typename TAdaptedString>
if (existingCopy) const char* saveString(const TAdaptedString& str) {
return existingCopy; if (str.isNull())
#endif return 0;
size_t n = str.size(); #if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
const char* existingCopy = findString(str.begin());
char* newCopy = allocString(n + 1); if (existingCopy)
if (newCopy) { return existingCopy;
str.copyTo(newCopy, n); #endif
newCopy[n] = 0; // force null-terminator
} size_t n = str.size();
return newCopy;
} char* newCopy = allocString(n + 1);
if (newCopy) {
void getFreeZone(char** zoneStart, size_t* zoneSize) const { str.copyTo(newCopy, n);
*zoneStart = _left; newCopy[n] = 0; // force null-terminator
*zoneSize = size_t(_right - _left); }
} return newCopy;
}
const char* saveStringFromFreeZone(size_t len) {
#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION void getFreeZone(char** zoneStart, size_t* zoneSize) const {
const char* dup = findString(_left); *zoneStart = _left;
if (dup) *zoneSize = size_t(_right - _left);
return dup; }
#endif
const char* saveStringFromFreeZone(size_t len) {
const char* str = _left; #if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
_left += len; const char* dup = findString(_left);
checkInvariants(); if (dup)
return str; return dup;
} #endif
void clear() { const char* str = _left;
_left = _begin; _left += len;
_right = _end; checkInvariants();
} return str;
}
bool canAlloc(size_t bytes) const {
return _left + bytes <= _right; void markAsOverflowed() {
} _overflowed = true;
}
bool owns(void* p) const {
return _begin <= p && p < _end; void clear() {
} _left = _begin;
_right = _end;
// Workaround for missing placement new _overflowed = false;
void* operator new(size_t, void* p) { }
return p;
} bool canAlloc(size_t bytes) const {
return _left + bytes <= _right;
// Squash the free space between strings and variants }
//
// _begin _end bool owns(void* p) const {
// v v return _begin <= p && p < _end;
// +-------------+--------------+ }
// | strings... | ...variants |
// +-------------+--------------+ // Workaround for missing placement new
// ^ void* operator new(size_t, void* p) {
// _left _right return p;
// }
// This funcion is called before a realloc.
ptrdiff_t squash() { // Squash the free space between strings and variants
char* new_right = addPadding(_left); //
if (new_right >= _right) // _begin _end
return 0; // v v
// +-------------+--------------+
size_t right_size = static_cast<size_t>(_end - _right); // | strings... | ...variants |
memmove(new_right, _right, right_size); // +-------------+--------------+
// ^
ptrdiff_t bytes_reclaimed = _right - new_right; // _left _right
_right = new_right; //
_end = new_right + right_size; // This funcion is called before a realloc.
return bytes_reclaimed; ptrdiff_t squash() {
} char* new_right = addPadding(_left);
if (new_right >= _right)
// Move all pointers together return 0;
// This funcion is called after a realloc.
void movePointers(ptrdiff_t offset) { size_t right_size = static_cast<size_t>(_end - _right);
_begin += offset; memmove(new_right, _right, right_size);
_left += offset;
_right += offset; ptrdiff_t bytes_reclaimed = _right - new_right;
_end += offset; _right = new_right;
} _end = new_right + right_size;
return bytes_reclaimed;
private: }
StringSlot* allocStringSlot() {
return allocRight<StringSlot>(); // Move all pointers together
} // This funcion is called after a realloc.
void movePointers(ptrdiff_t offset) {
void checkInvariants() { _begin += offset;
ARDUINOJSON_ASSERT(_begin <= _left); _left += offset;
ARDUINOJSON_ASSERT(_left <= _right); _right += offset;
ARDUINOJSON_ASSERT(_right <= _end); _end += offset;
ARDUINOJSON_ASSERT(isAligned(_right)); }
}
private:
#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION void checkInvariants() {
template <typename TIterator> ARDUINOJSON_ASSERT(_begin <= _left);
const char* findString(TIterator str) { ARDUINOJSON_ASSERT(_left <= _right);
for (char* next = _begin; next < _left; ++next) { ARDUINOJSON_ASSERT(_right <= _end);
char* begin = next; ARDUINOJSON_ASSERT(isAligned(_right));
}
// try to match
for (TIterator it = str; *it == *next; ++it) { #if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
if (*next++ == 0) template <typename TIterator>
return begin; const char* findString(TIterator str) {
} for (char* next = _begin; next < _left; ++next) {
char* begin = next;
// jump to next terminator
while (*next) ++next; // try to match
} for (TIterator it = str; *it == *next; ++it) {
return 0; if (*next++ == 0)
} return begin;
#endif }
char* allocString(size_t n) { // jump to next terminator
if (!canAlloc(n)) while (*next) ++next;
return 0; }
char* s = _left; return 0;
_left += n; }
checkInvariants(); #endif
return s;
} char* allocString(size_t n) {
if (!canAlloc(n)) {
template <typename T> _overflowed = true;
T* allocRight() { return 0;
return reinterpret_cast<T*>(allocRight(sizeof(T))); }
} char* s = _left;
_left += n;
void* allocRight(size_t bytes) { checkInvariants();
if (!canAlloc(bytes)) return s;
return 0; }
_right -= bytes;
return _right; template <typename T>
} T* allocRight() {
return reinterpret_cast<T*>(allocRight(sizeof(T)));
char *_begin, *_left, *_right, *_end; }
};
void* allocRight(size_t bytes) {
} // namespace ARDUINOJSON_NAMESPACE if (!canAlloc(bytes)) {
_overflowed = true;
return 0;
}
_right -= bytes;
return _right;
}
char *_begin, *_left, *_right, *_end;
bool _overflowed;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -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

View File

@@ -1,68 +1,68 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Strings/StringAdapters.hpp> #include <ArduinoJson/Strings/StringAdapters.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
// A special type of data that can be used to insert pregenerated JSON portions. // A special type of data that can be used to insert pregenerated JSON portions.
template <typename T> template <typename T>
class SerializedValue { class SerializedValue {
public: public:
explicit SerializedValue(T str) : _str(str) {} explicit SerializedValue(T str) : _str(str) {}
operator T() const { operator T() const {
return _str; return _str;
} }
const char* data() const { const char* data() const {
return _str.c_str(); return _str.c_str();
} }
size_t size() const { size_t size() const {
// CAUTION: the old Arduino String doesn't have size() // CAUTION: the old Arduino String doesn't have size()
return _str.length(); return _str.length();
} }
private: private:
T _str; T _str;
}; };
template <typename TChar> template <typename TChar>
class SerializedValue<TChar*> { class SerializedValue<TChar*> {
public: public:
explicit SerializedValue(TChar* p, size_t n) : _data(p), _size(n) {} explicit SerializedValue(TChar* p, size_t n) : _data(p), _size(n) {}
operator TChar*() const { operator TChar*() const {
return _data; return _data;
} }
TChar* data() const { TChar* data() const {
return _data; return _data;
} }
size_t size() const { size_t size() const {
return _size; return _size;
} }
private: private:
TChar* _data; TChar* _data;
size_t _size; size_t _size;
}; };
template <typename T> template <typename T>
inline SerializedValue<T> serialized(T str) { inline SerializedValue<T> serialized(T str) {
return SerializedValue<T>(str); return SerializedValue<T>(str);
} }
template <typename TChar> template <typename TChar>
inline SerializedValue<TChar*> serialized(TChar* p) { inline SerializedValue<TChar*> serialized(TChar* p) {
return SerializedValue<TChar*>(p, adaptString(p).size()); return SerializedValue<TChar*>(p, adaptString(p).size());
} }
template <typename TChar> template <typename TChar>
inline SerializedValue<TChar*> serialized(TChar* p, size_t n) { inline SerializedValue<TChar*> serialized(TChar* p, size_t n) {
return SerializedValue<TChar*>(p, n); return SerializedValue<TChar*>(p, n);
} }
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,21 +1,26 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Polyfills/type_traits.hpp> #include <ArduinoJson/Polyfills/type_traits.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
struct Visitable { template <typename TResult>
// template<Visitor> struct Visitor {
// void accept(Visitor&) const; typedef TResult result_type;
}; };
template <typename T> struct Visitable {
struct IsVisitable : is_base_of<Visitable, T> {}; // template<Visitor>
// void accept(Visitor&) const;
template <typename T> };
struct IsVisitable<T&> : IsVisitable<T> {};
} // namespace ARDUINOJSON_NAMESPACE template <typename T>
struct IsVisitable : is_base_of<Visitable, T> {};
template <typename T>
struct IsVisitable<T&> : IsVisitable<T> {};
} // namespace ARDUINOJSON_NAMESPACE

File diff suppressed because it is too large Load Diff

View File

@@ -1,193 +1,203 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/MsgPack/endianess.hpp> #include <ArduinoJson/MsgPack/endianess.hpp>
#include <ArduinoJson/Polyfills/assert.hpp> #include <ArduinoJson/Polyfills/assert.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp> #include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Serialization/measure.hpp> #include <ArduinoJson/Serialization/CountingDecorator.hpp>
#include <ArduinoJson/Serialization/serialize.hpp> #include <ArduinoJson/Serialization/measure.hpp>
#include <ArduinoJson/Variant/VariantData.hpp> #include <ArduinoJson/Serialization/serialize.hpp>
#include <ArduinoJson/Variant/VariantData.hpp>
namespace ARDUINOJSON_NAMESPACE {
namespace ARDUINOJSON_NAMESPACE {
template <typename TWriter>
class MsgPackSerializer { template <typename TWriter>
public: class MsgPackSerializer : public Visitor<size_t> {
MsgPackSerializer(TWriter writer) : _writer(writer), _bytesWritten(0) {} public:
MsgPackSerializer(TWriter writer) : _writer(writer) {}
template <typename T>
typename enable_if<sizeof(T) == 4>::type visitFloat(T value32) { template <typename T>
writeByte(0xCA); typename enable_if<sizeof(T) == 4, size_t>::type visitFloat(T value32) {
writeInteger(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) { template <typename T>
float value32 = float(value64); ARDUINOJSON_NO_SANITIZE("float-cast-overflow")
if (value32 == value64) { typename enable_if<sizeof(T) == 8, size_t>::type visitFloat(T value64) {
writeByte(0xCA); float value32 = float(value64);
writeInteger(value32); if (value32 == value64) {
} else { writeByte(0xCA);
writeByte(0xCB); writeInteger(value32);
writeInteger(value64); } else {
} writeByte(0xCB);
} writeInteger(value64);
}
void visitArray(const CollectionData& array) { return bytesWritten();
size_t n = array.size(); }
if (n < 0x10) {
writeByte(uint8_t(0x90 + array.size())); size_t visitArray(const CollectionData& array) {
} else if (n < 0x10000) { size_t n = array.size();
writeByte(0xDC); if (n < 0x10) {
writeInteger(uint16_t(n)); writeByte(uint8_t(0x90 + array.size()));
} else { } else if (n < 0x10000) {
writeByte(0xDD); writeByte(0xDC);
writeInteger(uint32_t(n)); writeInteger(uint16_t(n));
} } else {
for (VariantSlot* slot = array.head(); slot; slot = slot->next()) { writeByte(0xDD);
slot->data()->accept(*this); writeInteger(uint32_t(n));
} }
} for (VariantSlot* slot = array.head(); slot; slot = slot->next()) {
slot->data()->accept(*this);
void visitObject(const CollectionData& object) { }
size_t n = object.size(); return bytesWritten();
if (n < 0x10) { }
writeByte(uint8_t(0x80 + n));
} else if (n < 0x10000) { size_t visitObject(const CollectionData& object) {
writeByte(0xDE); size_t n = object.size();
writeInteger(uint16_t(n)); if (n < 0x10) {
} else { writeByte(uint8_t(0x80 + n));
writeByte(0xDF); } else if (n < 0x10000) {
writeInteger(uint32_t(n)); writeByte(0xDE);
} writeInteger(uint16_t(n));
for (VariantSlot* slot = object.head(); slot; slot = slot->next()) { } else {
visitString(slot->key()); writeByte(0xDF);
slot->data()->accept(*this); writeInteger(uint32_t(n));
} }
} for (VariantSlot* slot = object.head(); slot; slot = slot->next()) {
visitString(slot->key());
void visitString(const char* value) { slot->data()->accept(*this);
ARDUINOJSON_ASSERT(value != NULL); }
return bytesWritten();
size_t n = strlen(value); }
if (n < 0x20) { size_t visitString(const char* value) {
writeByte(uint8_t(0xA0 + n)); ARDUINOJSON_ASSERT(value != NULL);
} else if (n < 0x100) {
writeByte(0xD9); size_t n = strlen(value);
writeInteger(uint8_t(n));
} else if (n < 0x10000) { if (n < 0x20) {
writeByte(0xDA); writeByte(uint8_t(0xA0 + n));
writeInteger(uint16_t(n)); } else if (n < 0x100) {
} else { writeByte(0xD9);
writeByte(0xDB); writeInteger(uint8_t(n));
writeInteger(uint32_t(n)); } else if (n < 0x10000) {
} writeByte(0xDA);
writeBytes(reinterpret_cast<const uint8_t*>(value), n); writeInteger(uint16_t(n));
} } else {
writeByte(0xDB);
void visitRawJson(const char* data, size_t size) { writeInteger(uint32_t(n));
writeBytes(reinterpret_cast<const uint8_t*>(data), size); }
} writeBytes(reinterpret_cast<const uint8_t*>(value), n);
return bytesWritten();
void visitNegativeInteger(UInt value) { }
UInt negated = UInt(~value + 1);
if (value <= 0x20) { size_t visitRawJson(const char* data, size_t size) {
writeInteger(int8_t(negated)); writeBytes(reinterpret_cast<const uint8_t*>(data), size);
} else if (value <= 0x80) { return bytesWritten();
writeByte(0xD0); }
writeInteger(int8_t(negated));
} else if (value <= 0x8000) { size_t visitNegativeInteger(UInt value) {
writeByte(0xD1); UInt negated = UInt(~value + 1);
writeInteger(int16_t(negated)); if (value <= 0x20) {
} else if (value <= 0x80000000) { writeInteger(int8_t(negated));
writeByte(0xD2); } else if (value <= 0x80) {
writeInteger(int32_t(negated)); writeByte(0xD0);
} writeInteger(int8_t(negated));
#if ARDUINOJSON_USE_LONG_LONG } else if (value <= 0x8000) {
else { writeByte(0xD1);
writeByte(0xD3); writeInteger(int16_t(negated));
writeInteger(int64_t(negated)); } else if (value <= 0x80000000) {
} writeByte(0xD2);
#endif writeInteger(int32_t(negated));
} }
#if ARDUINOJSON_USE_LONG_LONG
void visitPositiveInteger(UInt value) { else {
if (value <= 0x7F) { writeByte(0xD3);
writeInteger(uint8_t(value)); writeInteger(int64_t(negated));
} else if (value <= 0xFF) { }
writeByte(0xCC); #endif
writeInteger(uint8_t(value)); return bytesWritten();
} else if (value <= 0xFFFF) { }
writeByte(0xCD);
writeInteger(uint16_t(value)); size_t visitPositiveInteger(UInt value) {
} if (value <= 0x7F) {
#if ARDUINOJSON_USE_LONG_LONG writeInteger(uint8_t(value));
else if (value <= 0xFFFFFFFF) } else if (value <= 0xFF) {
#else writeByte(0xCC);
else writeInteger(uint8_t(value));
#endif } else if (value <= 0xFFFF) {
{ writeByte(0xCD);
writeByte(0xCE); writeInteger(uint16_t(value));
writeInteger(uint32_t(value)); }
} #if ARDUINOJSON_USE_LONG_LONG
#if ARDUINOJSON_USE_LONG_LONG else if (value <= 0xFFFFFFFF)
else { #else
writeByte(0xCF); else
writeInteger(uint64_t(value)); #endif
} {
#endif writeByte(0xCE);
} writeInteger(uint32_t(value));
}
void visitBoolean(bool value) { #if ARDUINOJSON_USE_LONG_LONG
writeByte(value ? 0xC3 : 0xC2); else {
} writeByte(0xCF);
writeInteger(uint64_t(value));
void visitNull() { }
writeByte(0xC0); #endif
} return bytesWritten();
}
size_t bytesWritten() const {
return _bytesWritten; size_t visitBoolean(bool value) {
} writeByte(value ? 0xC3 : 0xC2);
return bytesWritten();
private: }
void writeByte(uint8_t c) {
_bytesWritten += _writer.write(c); size_t visitNull() {
} writeByte(0xC0);
return bytesWritten();
void writeBytes(const uint8_t* p, size_t n) { }
_bytesWritten += _writer.write(p, n);
} private:
size_t bytesWritten() const {
template <typename T> return _writer.count();
void writeInteger(T value) { }
fixEndianess(value);
writeBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value)); void writeByte(uint8_t c) {
} _writer.write(c);
}
TWriter _writer;
size_t _bytesWritten; void writeBytes(const uint8_t* p, size_t n) {
}; _writer.write(p, n);
}
template <typename TSource, typename TDestination>
inline size_t serializeMsgPack(const TSource& source, TDestination& output) { template <typename T>
return serialize<MsgPackSerializer>(source, output); void writeInteger(T value) {
} fixEndianess(value);
writeBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
template <typename TSource> }
inline size_t serializeMsgPack(const TSource& source, void* output,
size_t size) { CountingDecorator<TWriter> _writer;
return serialize<MsgPackSerializer>(source, output, size); };
}
template <typename TSource, typename TDestination>
template <typename TSource> inline size_t serializeMsgPack(const TSource& source, TDestination& output) {
inline size_t measureMsgPack(const TSource& source) { return serialize<MsgPackSerializer>(source, output);
return measure<MsgPackSerializer>(source); }
}
template <typename TSource>
} // namespace ARDUINOJSON_NAMESPACE inline size_t serializeMsgPack(const TSource& source, void* output,
size_t size) {
return serialize<MsgPackSerializer>(source, output, size);
}
template <typename TSource>
inline size_t measureMsgPack(const TSource& source) {
return measure<MsgPackSerializer>(source);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,41 +1,41 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Polyfills/type_traits.hpp> #include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Polyfills/utility.hpp> #include <ArduinoJson/Polyfills/utility.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
#if ARDUINOJSON_LITTLE_ENDIAN #if ARDUINOJSON_LITTLE_ENDIAN
inline void fixEndianess(uint8_t *p, integral_constant<size_t, 8>) { inline void fixEndianess(uint8_t *p, integral_constant<size_t, 8>) {
swap(p[0], p[7]); swap(p[0], p[7]);
swap(p[1], p[6]); swap(p[1], p[6]);
swap(p[2], p[5]); swap(p[2], p[5]);
swap(p[3], p[4]); swap(p[3], p[4]);
} }
inline void fixEndianess(uint8_t *p, integral_constant<size_t, 4>) { inline void fixEndianess(uint8_t *p, integral_constant<size_t, 4>) {
swap(p[0], p[3]); swap(p[0], p[3]);
swap(p[1], p[2]); swap(p[1], p[2]);
} }
inline void fixEndianess(uint8_t *p, integral_constant<size_t, 2>) { inline void fixEndianess(uint8_t *p, integral_constant<size_t, 2>) {
swap(p[0], p[1]); swap(p[0], p[1]);
} }
inline void fixEndianess(uint8_t *, integral_constant<size_t, 1>) {} inline void fixEndianess(uint8_t *, integral_constant<size_t, 1>) {}
template <typename T> template <typename T>
inline void fixEndianess(T &value) { inline void fixEndianess(T &value) {
fixEndianess(reinterpret_cast<uint8_t *>(&value), fixEndianess(reinterpret_cast<uint8_t *>(&value),
integral_constant<size_t, sizeof(T)>()); integral_constant<size_t, sizeof(T)>());
} }
#else #else
template <typename T> template <typename T>
inline void fixEndianess(T &) {} inline void fixEndianess(T &) {}
#endif #endif
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,18 +1,18 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
inline void doubleToFloat(const uint8_t d[8], uint8_t f[4]) { inline void doubleToFloat(const uint8_t d[8], uint8_t f[4]) {
f[0] = uint8_t((d[0] & 0xC0) | (d[0] << 3 & 0x3f) | (d[1] >> 5)); f[0] = uint8_t((d[0] & 0xC0) | (d[0] << 3 & 0x3f) | (d[1] >> 5));
f[1] = uint8_t((d[1] << 3) | (d[2] >> 5)); f[1] = uint8_t((d[1] << 3) | (d[2] >> 5));
f[2] = uint8_t((d[2] << 3) | (d[3] >> 5)); f[2] = uint8_t((d[2] << 3) | (d[3] >> 5));
f[3] = uint8_t((d[3] << 3) | (d[4] >> 5)); f[3] = uint8_t((d[3] << 3) | (d[4] >> 5));
} }
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,49 +1,26 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Configuration.hpp> #include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/version.hpp> #include <ArduinoJson/Polyfills/preprocessor.hpp>
#include <ArduinoJson/version.hpp>
#ifndef ARDUINOJSON_NAMESPACE
#ifndef ARDUINOJSON_NAMESPACE
#define ARDUINOJSON_HEX_DIGIT_0000() 0
#define ARDUINOJSON_HEX_DIGIT_0001() 1 #define ARDUINOJSON_NAMESPACE \
#define ARDUINOJSON_HEX_DIGIT_0010() 2 ARDUINOJSON_CONCAT4( \
#define ARDUINOJSON_HEX_DIGIT_0011() 3 ARDUINOJSON_CONCAT4(ArduinoJson, ARDUINOJSON_VERSION_MAJOR, \
#define ARDUINOJSON_HEX_DIGIT_0100() 4 ARDUINOJSON_VERSION_MINOR, \
#define ARDUINOJSON_HEX_DIGIT_0101() 5 ARDUINOJSON_VERSION_REVISION), \
#define ARDUINOJSON_HEX_DIGIT_0110() 6 _, \
#define ARDUINOJSON_HEX_DIGIT_0111() 7 ARDUINOJSON_HEX_DIGIT(ARDUINOJSON_ENABLE_PROGMEM, \
#define ARDUINOJSON_HEX_DIGIT_1000() 8 ARDUINOJSON_USE_LONG_LONG, ARDUINOJSON_USE_DOUBLE, \
#define ARDUINOJSON_HEX_DIGIT_1001() 9 ARDUINOJSON_ENABLE_STRING_DEDUPLICATION), \
#define ARDUINOJSON_HEX_DIGIT_1010() A ARDUINOJSON_HEX_DIGIT( \
#define ARDUINOJSON_HEX_DIGIT_1011() B ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY, \
#define ARDUINOJSON_HEX_DIGIT_1100() C ARDUINOJSON_ENABLE_COMMENTS, ARDUINOJSON_DECODE_UNICODE))
#define ARDUINOJSON_HEX_DIGIT_1101() D
#define ARDUINOJSON_HEX_DIGIT_1110() E #endif
#define ARDUINOJSON_HEX_DIGIT_1111() F
#define ARDUINOJSON_HEX_DIGIT_(A, B, C, D) ARDUINOJSON_HEX_DIGIT_##A##B##C##D()
#define ARDUINOJSON_HEX_DIGIT(A, B, C, D) ARDUINOJSON_HEX_DIGIT_(A, B, C, D)
#define ARDUINOJSON_CONCAT_(A, B) A##B
#define ARDUINOJSON_CONCAT2(A, B) ARDUINOJSON_CONCAT_(A, B)
#define ARDUINOJSON_CONCAT4(A, B, C, D) \
ARDUINOJSON_CONCAT2(ARDUINOJSON_CONCAT2(A, B), ARDUINOJSON_CONCAT2(C, D))
#define ARDUINOJSON_NAMESPACE \
ARDUINOJSON_CONCAT4( \
ARDUINOJSON_CONCAT4(ArduinoJson, ARDUINOJSON_VERSION_MAJOR, \
ARDUINOJSON_VERSION_MINOR, \
ARDUINOJSON_VERSION_REVISION), \
_, \
ARDUINOJSON_HEX_DIGIT(0, ARDUINOJSON_USE_LONG_LONG, \
ARDUINOJSON_USE_DOUBLE, \
ARDUINOJSON_ENABLE_STRING_DEDUPLICATION), \
ARDUINOJSON_HEX_DIGIT( \
ARDUINOJSON_ENABLE_NAN, ARDUINOJSON_ENABLE_INFINITY, \
ARDUINOJSON_ENABLE_COMMENTS, ARDUINOJSON_DECODE_UNICODE))
#endif

View File

@@ -1,17 +1,17 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Configuration.hpp> #include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
#if ARDUINOJSON_USE_DOUBLE #if ARDUINOJSON_USE_DOUBLE
typedef double Float; typedef double Float;
#else #else
typedef float Float; typedef float Float;
#endif #endif
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,87 +1,87 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Configuration.hpp> #include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Numbers/FloatTraits.hpp> #include <ArduinoJson/Numbers/FloatTraits.hpp>
#include <ArduinoJson/Polyfills/math.hpp> #include <ArduinoJson/Polyfills/math.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename TFloat> template <typename TFloat>
struct FloatParts { struct FloatParts {
uint32_t integral; uint32_t integral;
uint32_t decimal; uint32_t decimal;
int16_t exponent; int16_t exponent;
int8_t decimalPlaces; int8_t decimalPlaces;
FloatParts(TFloat value) { FloatParts(TFloat value) {
uint32_t maxDecimalPart = sizeof(TFloat) >= 8 ? 1000000000 : 1000000; uint32_t maxDecimalPart = sizeof(TFloat) >= 8 ? 1000000000 : 1000000;
decimalPlaces = sizeof(TFloat) >= 8 ? 9 : 6; decimalPlaces = sizeof(TFloat) >= 8 ? 9 : 6;
exponent = normalize(value); exponent = normalize(value);
integral = uint32_t(value); integral = uint32_t(value);
// reduce number of decimal places by the number of integral places // reduce number of decimal places by the number of integral places
for (uint32_t tmp = integral; tmp >= 10; tmp /= 10) { for (uint32_t tmp = integral; tmp >= 10; tmp /= 10) {
maxDecimalPart /= 10; maxDecimalPart /= 10;
decimalPlaces--; decimalPlaces--;
} }
TFloat remainder = (value - TFloat(integral)) * TFloat(maxDecimalPart); TFloat remainder = (value - TFloat(integral)) * TFloat(maxDecimalPart);
decimal = uint32_t(remainder); decimal = uint32_t(remainder);
remainder = remainder - TFloat(decimal); remainder = remainder - TFloat(decimal);
// rounding: // rounding:
// increment by 1 if remainder >= 0.5 // increment by 1 if remainder >= 0.5
decimal += uint32_t(remainder * 2); decimal += uint32_t(remainder * 2);
if (decimal >= maxDecimalPart) { if (decimal >= maxDecimalPart) {
decimal = 0; decimal = 0;
integral++; integral++;
if (exponent && integral >= 10) { if (exponent && integral >= 10) {
exponent++; exponent++;
integral = 1; integral = 1;
} }
} }
// remove trailing zeros // remove trailing zeros
while (decimal % 10 == 0 && decimalPlaces > 0) { while (decimal % 10 == 0 && decimalPlaces > 0) {
decimal /= 10; decimal /= 10;
decimalPlaces--; decimalPlaces--;
} }
} }
static int16_t normalize(TFloat& value) { static int16_t normalize(TFloat& value) {
typedef FloatTraits<TFloat> traits; typedef FloatTraits<TFloat> traits;
int16_t powersOf10 = 0; int16_t powersOf10 = 0;
int8_t index = sizeof(TFloat) == 8 ? 8 : 5; int8_t index = sizeof(TFloat) == 8 ? 8 : 5;
int bit = 1 << index; int bit = 1 << index;
if (value >= ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD) { if (value >= ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD) {
for (; index >= 0; index--) { for (; index >= 0; index--) {
if (value >= traits::positiveBinaryPowerOfTen(index)) { if (value >= traits::positiveBinaryPowerOfTen(index)) {
value *= traits::negativeBinaryPowerOfTen(index); value *= traits::negativeBinaryPowerOfTen(index);
powersOf10 = int16_t(powersOf10 + bit); powersOf10 = int16_t(powersOf10 + bit);
} }
bit >>= 1; bit >>= 1;
} }
} }
if (value > 0 && value <= ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD) { if (value > 0 && value <= ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD) {
for (; index >= 0; index--) { for (; index >= 0; index--) {
if (value < traits::negativeBinaryPowerOfTenPlusOne(index)) { if (value < traits::negativeBinaryPowerOfTenPlusOne(index)) {
value *= traits::positiveBinaryPowerOfTen(index); value *= traits::positiveBinaryPowerOfTen(index);
powersOf10 = int16_t(powersOf10 - bit); powersOf10 = int16_t(powersOf10 - bit);
} }
bit >>= 1; bit >>= 1;
} }
} }
return powersOf10; return powersOf10;
} }
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,181 +1,201 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <stddef.h> // for size_t #include <stddef.h> // for size_t
#include <stdint.h> #include <stdint.h>
#include <ArduinoJson/Configuration.hpp> #include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Polyfills/alias_cast.hpp> #include <ArduinoJson/Polyfills/alias_cast.hpp>
#include <ArduinoJson/Polyfills/math.hpp> #include <ArduinoJson/Polyfills/math.hpp>
#include <ArduinoJson/Polyfills/preprocessor.hpp>
namespace ARDUINOJSON_NAMESPACE { #include <ArduinoJson/Polyfills/static_array.hpp>
template <typename T, size_t = sizeof(T)> namespace ARDUINOJSON_NAMESPACE {
struct FloatTraits {};
template <typename T, size_t = sizeof(T)>
template <typename T> struct FloatTraits {};
struct FloatTraits<T, 8 /*64bits*/> {
typedef uint64_t mantissa_type; template <typename T>
static const short mantissa_bits = 52; struct FloatTraits<T, 8 /*64bits*/> {
static const mantissa_type mantissa_max = typedef uint64_t mantissa_type;
(mantissa_type(1) << mantissa_bits) - 1; static const short mantissa_bits = 52;
static const mantissa_type mantissa_max =
typedef int16_t exponent_type; (mantissa_type(1) << mantissa_bits) - 1;
static const exponent_type exponent_max = 308;
typedef int16_t exponent_type;
template <typename TExponent> static const exponent_type exponent_max = 308;
static T make_float(T m, TExponent e) {
if (e > 0) { template <typename TExponent>
for (uint8_t index = 0; e != 0; index++) { static T make_float(T m, TExponent e) {
if (e & 1) if (e > 0) {
m *= positiveBinaryPowerOfTen(index); for (uint8_t index = 0; e != 0; index++) {
e >>= 1; if (e & 1)
} m *= positiveBinaryPowerOfTen(index);
} else { e >>= 1;
e = TExponent(-e); }
for (uint8_t index = 0; e != 0; index++) { } else {
if (e & 1) e = TExponent(-e);
m *= negativeBinaryPowerOfTen(index); for (uint8_t index = 0; e != 0; index++) {
e >>= 1; if (e & 1)
} m *= negativeBinaryPowerOfTen(index);
} e >>= 1;
return m; }
} }
return m;
static T positiveBinaryPowerOfTen(int index) { }
static T factors[] = {
1e1, static T positiveBinaryPowerOfTen(int index) {
1e2, ARDUINOJSON_DEFINE_STATIC_ARRAY( //
1e4, uint32_t, factors,
1e8, ARDUINOJSON_EXPAND18({
1e16, 0x40240000, 0x00000000, // 1e1
forge(0x4693B8B5, 0xB5056E17), // 1e32 0x40590000, 0x00000000, // 1e2
forge(0x4D384F03, 0xE93FF9F5), // 1e64 0x40C38800, 0x00000000, // 1e4
forge(0x5A827748, 0xF9301D32), // 1e128 0x4197D784, 0x00000000, // 1e8
forge(0x75154FDD, 0x7F73BF3C) // 1e256 0x4341C379, 0x37E08000, // 1e16
}; 0x4693B8B5, 0xB5056E17, // 1e32
return factors[index]; 0x4D384F03, 0xE93FF9F5, // 1e64
} 0x5A827748, 0xF9301D32, // 1e128
0x75154FDD, 0x7F73BF3C // 1e256
static T negativeBinaryPowerOfTen(int index) { }));
static T factors[] = { return forge(
forge(0x3FB99999, 0x9999999A), // 1e-1 ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index),
forge(0x3F847AE1, 0x47AE147B), // 1e-2 ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1));
forge(0x3F1A36E2, 0xEB1C432D), // 1e-4 }
forge(0x3E45798E, 0xE2308C3A), // 1e-8
forge(0x3C9CD2B2, 0x97D889BC), // 1e-16 static T negativeBinaryPowerOfTen(int index) {
forge(0x3949F623, 0xD5A8A733), // 1e-32 ARDUINOJSON_DEFINE_STATIC_ARRAY( //
forge(0x32A50FFD, 0x44F4A73D), // 1e-64 uint32_t, factors,
forge(0x255BBA08, 0xCF8C979D), // 1e-128 ARDUINOJSON_EXPAND18({
forge(0x0AC80628, 0x64AC6F43) // 1e-256 0x3FB99999, 0x9999999A, // 1e-1
}; 0x3F847AE1, 0x47AE147B, // 1e-2
return factors[index]; 0x3F1A36E2, 0xEB1C432D, // 1e-4
} 0x3E45798E, 0xE2308C3A, // 1e-8
0x3C9CD2B2, 0x97D889BC, // 1e-16
static T negativeBinaryPowerOfTenPlusOne(int index) { 0x3949F623, 0xD5A8A733, // 1e-32
static T factors[] = { 0x32A50FFD, 0x44F4A73D, // 1e-64
1e0, 0x255BBA08, 0xCF8C979D, // 1e-128
forge(0x3FB99999, 0x9999999A), // 1e-1 0x0AC80628, 0x64AC6F43 // 1e-256
forge(0x3F50624D, 0xD2F1A9FC), // 1e-3 }));
forge(0x3E7AD7F2, 0x9ABCAF48), // 1e-7 return forge(
forge(0x3CD203AF, 0x9EE75616), // 1e-15 ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index),
forge(0x398039D6, 0x65896880), // 1e-31 ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1));
forge(0x32DA53FC, 0x9631D10D), // 1e-63 }
forge(0x25915445, 0x81B7DEC2), // 1e-127
forge(0x0AFE07B2, 0x7DD78B14) // 1e-255 static T negativeBinaryPowerOfTenPlusOne(int index) {
}; ARDUINOJSON_DEFINE_STATIC_ARRAY( //
return factors[index]; uint32_t, factors,
} ARDUINOJSON_EXPAND18({
0x3FF00000, 0x00000000, // 1e0
static T nan() { 0x3FB99999, 0x9999999A, // 1e-1
return forge(0x7ff80000, 0x00000000); 0x3F50624D, 0xD2F1A9FC, // 1e-3
} 0x3E7AD7F2, 0x9ABCAF48, // 1e-7
0x3CD203AF, 0x9EE75616, // 1e-15
static T inf() { 0x398039D6, 0x65896880, // 1e-31
return forge(0x7ff00000, 0x00000000); 0x32DA53FC, 0x9631D10D, // 1e-63
} 0x25915445, 0x81B7DEC2, // 1e-127
0x0AFE07B2, 0x7DD78B14 // 1e-255
static T highest() { }));
return forge(0x7FEFFFFF, 0xFFFFFFFF); return forge(
} ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index),
ARDUINOJSON_READ_STATIC_ARRAY(uint32_t, factors, 2 * index + 1));
static T lowest() { }
return forge(0xFFEFFFFF, 0xFFFFFFFF);
} static T nan() {
return forge(0x7ff80000, 0x00000000);
// constructs a double floating point values from its binary representation }
// we use this function to workaround platforms with single precision literals
// (for example, when -fsingle-precision-constant is passed to GCC) static T inf() {
static T forge(uint32_t msb, uint32_t lsb) { return forge(0x7ff00000, 0x00000000);
return alias_cast<T>((uint64_t(msb) << 32) | lsb); }
}
}; static T highest() {
return forge(0x7FEFFFFF, 0xFFFFFFFF);
template <typename T> }
struct FloatTraits<T, 4 /*32bits*/> {
typedef uint32_t mantissa_type; static T lowest() {
static const short mantissa_bits = 23; return forge(0xFFEFFFFF, 0xFFFFFFFF);
static const mantissa_type mantissa_max = }
(mantissa_type(1) << mantissa_bits) - 1;
// constructs a double floating point values from its binary representation
typedef int8_t exponent_type; // we use this function to workaround platforms with single precision literals
static const exponent_type exponent_max = 38; // (for example, when -fsingle-precision-constant is passed to GCC)
static T forge(uint32_t msb, uint32_t lsb) {
template <typename TExponent> return alias_cast<T>((uint64_t(msb) << 32) | lsb);
static T make_float(T m, TExponent e) { }
if (e > 0) { };
for (uint8_t index = 0; e != 0; index++) {
if (e & 1) template <typename T>
m *= positiveBinaryPowerOfTen(index); struct FloatTraits<T, 4 /*32bits*/> {
e >>= 1; typedef uint32_t mantissa_type;
} static const short mantissa_bits = 23;
} else { static const mantissa_type mantissa_max =
e = -e; (mantissa_type(1) << mantissa_bits) - 1;
for (uint8_t index = 0; e != 0; index++) {
if (e & 1) typedef int8_t exponent_type;
m *= negativeBinaryPowerOfTen(index); static const exponent_type exponent_max = 38;
e >>= 1;
} template <typename TExponent>
} static T make_float(T m, TExponent e) {
return m; if (e > 0) {
} for (uint8_t index = 0; e != 0; index++) {
if (e & 1)
static T positiveBinaryPowerOfTen(int index) { m *= positiveBinaryPowerOfTen(index);
static T factors[] = {1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f}; e >>= 1;
return factors[index]; }
} } else {
e = -e;
static T negativeBinaryPowerOfTen(int index) { for (uint8_t index = 0; e != 0; index++) {
static T factors[] = {1e-1f, 1e-2f, 1e-4f, 1e-8f, 1e-16f, 1e-32f}; if (e & 1)
return factors[index]; m *= negativeBinaryPowerOfTen(index);
} e >>= 1;
}
static T negativeBinaryPowerOfTenPlusOne(int index) { }
static T factors[] = {1e0f, 1e-1f, 1e-3f, 1e-7f, 1e-15f, 1e-31f}; return m;
return factors[index]; }
}
static T positiveBinaryPowerOfTen(int index) {
static T forge(uint32_t bits) { ARDUINOJSON_DEFINE_STATIC_ARRAY(
return alias_cast<T>(bits); T, factors,
} ARDUINOJSON_EXPAND6({1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f}));
return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index);
static T nan() { }
return forge(0x7fc00000);
} static T negativeBinaryPowerOfTen(int index) {
ARDUINOJSON_DEFINE_STATIC_ARRAY(
static T inf() { T, factors,
return forge(0x7f800000); ARDUINOJSON_EXPAND6({1e-1f, 1e-2f, 1e-4f, 1e-8f, 1e-16f, 1e-32f}));
} return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index);
}
static T highest() {
return forge(0x7f7fffff); static T negativeBinaryPowerOfTenPlusOne(int index) {
} ARDUINOJSON_DEFINE_STATIC_ARRAY(
T, factors,
static T lowest() { ARDUINOJSON_EXPAND6({1e0f, 1e-1f, 1e-3f, 1e-7f, 1e-15f, 1e-31f}));
return forge(0xFf7fffff); return ARDUINOJSON_READ_STATIC_ARRAY(T, factors, index);
} }
};
} // namespace ARDUINOJSON_NAMESPACE static T forge(uint32_t bits) {
return alias_cast<T>(bits);
}
static T nan() {
return forge(0x7fc00000);
}
static T inf() {
return forge(0x7f800000);
}
static T highest() {
return forge(0x7f7fffff);
}
static T lowest() {
return forge(0xFf7fffff);
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,32 +1,32 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Configuration.hpp> #include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
#include <stdint.h> // int64_t #include <stdint.h> // int64_t
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
#if ARDUINOJSON_USE_LONG_LONG #if ARDUINOJSON_USE_LONG_LONG
typedef int64_t Integer; typedef int64_t Integer;
typedef uint64_t UInt; typedef uint64_t UInt;
#else #else
typedef long Integer; typedef long Integer;
typedef unsigned long UInt; typedef unsigned long UInt;
#endif #endif
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE
#if ARDUINOJSON_HAS_LONG_LONG && !ARDUINOJSON_USE_LONG_LONG #if ARDUINOJSON_HAS_LONG_LONG && !ARDUINOJSON_USE_LONG_LONG
#define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T) \ #define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T) \
static_assert(sizeof(T) <= sizeof(ARDUINOJSON_NAMESPACE::Integer), \ static_assert(sizeof(T) <= sizeof(ARDUINOJSON_NAMESPACE::Integer), \
"To use 64-bit integers with ArduinoJson, you must set " \ "To use 64-bit integers with ArduinoJson, you must set " \
"ARDUINOJSON_USE_LONG_LONG to 1. See " \ "ARDUINOJSON_USE_LONG_LONG to 1. See " \
"https://arduinojson.org/v6/api/config/use_long_long/"); "https://arduinojson.org/v6/api/config/use_long_long/");
#else #else
#define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T) #define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T)
#endif #endif

View File

@@ -1,121 +1,121 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Numbers/Integer.hpp> #include <ArduinoJson/Numbers/Integer.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp> #include <ArduinoJson/Polyfills/type_traits.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
enum CompareResult { enum CompareResult {
COMPARE_RESULT_DIFFER = 0, COMPARE_RESULT_DIFFER = 0,
COMPARE_RESULT_EQUAL = 1, COMPARE_RESULT_EQUAL = 1,
COMPARE_RESULT_GREATER = 2, COMPARE_RESULT_GREATER = 2,
COMPARE_RESULT_LESS = 4, COMPARE_RESULT_LESS = 4,
COMPARE_RESULT_GREATER_OR_EQUAL = 3, COMPARE_RESULT_GREATER_OR_EQUAL = 3,
COMPARE_RESULT_LESS_OR_EQUAL = 5 COMPARE_RESULT_LESS_OR_EQUAL = 5
}; };
template <typename T> template <typename T>
CompareResult arithmeticCompare(const T &lhs, const T &rhs) { CompareResult arithmeticCompare(const T &lhs, const T &rhs) {
if (lhs < rhs) if (lhs < rhs)
return COMPARE_RESULT_LESS; return COMPARE_RESULT_LESS;
else if (lhs > rhs) else if (lhs > rhs)
return COMPARE_RESULT_GREATER; return COMPARE_RESULT_GREATER;
else else
return COMPARE_RESULT_EQUAL; return COMPARE_RESULT_EQUAL;
} }
template <typename T1, typename T2> template <typename T1, typename T2>
CompareResult arithmeticCompare( CompareResult arithmeticCompare(
const T1 &lhs, const T2 &rhs, const T1 &lhs, const T2 &rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value && typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
sizeof(T1) < sizeof(T2), sizeof(T1) < sizeof(T2),
int // Using int instead of void to avoid C2572 on int // Using int instead of void to avoid C2572 on
// Visual Studio 2012, 2013, and 2015 // Visual Studio 2012, 2013, and 2015
>::type * = 0) { >::type * = 0) {
return arithmeticCompare<T2>(static_cast<T2>(lhs), rhs); return arithmeticCompare<T2>(static_cast<T2>(lhs), rhs);
} }
template <typename T1, typename T2> template <typename T1, typename T2>
CompareResult arithmeticCompare( CompareResult arithmeticCompare(
const T1 &lhs, const T2 &rhs, const T1 &lhs, const T2 &rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value && typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
sizeof(T2) < sizeof(T1)>::type * = 0) { sizeof(T2) < sizeof(T1)>::type * = 0) {
return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs)); return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
} }
template <typename T1, typename T2> template <typename T1, typename T2>
CompareResult arithmeticCompare( CompareResult arithmeticCompare(
const T1 &lhs, const T2 &rhs, const T1 &lhs, const T2 &rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value && typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
is_signed<T1>::value == is_signed<T2>::value && is_signed<T1>::value == is_signed<T2>::value &&
sizeof(T2) == sizeof(T1)>::type * = 0) { sizeof(T2) == sizeof(T1)>::type * = 0) {
return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs)); return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
} }
template <typename T1, typename T2> template <typename T1, typename T2>
CompareResult arithmeticCompare( CompareResult arithmeticCompare(
const T1 &lhs, const T2 &rhs, const T1 &lhs, const T2 &rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value && typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
is_unsigned<T1>::value && is_signed<T2>::value && is_unsigned<T1>::value && is_signed<T2>::value &&
sizeof(T2) == sizeof(T1)>::type * = 0) { sizeof(T2) == sizeof(T1)>::type * = 0) {
if (rhs < 0) if (rhs < 0)
return COMPARE_RESULT_GREATER; return COMPARE_RESULT_GREATER;
return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs)); return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
} }
template <typename T1, typename T2> template <typename T1, typename T2>
CompareResult arithmeticCompare( CompareResult arithmeticCompare(
const T1 &lhs, const T2 &rhs, const T1 &lhs, const T2 &rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value && typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
is_signed<T1>::value && is_unsigned<T2>::value && is_signed<T1>::value && is_unsigned<T2>::value &&
sizeof(T2) == sizeof(T1)>::type * = 0) { sizeof(T2) == sizeof(T1)>::type * = 0) {
if (lhs < 0) if (lhs < 0)
return COMPARE_RESULT_LESS; return COMPARE_RESULT_LESS;
return arithmeticCompare<T2>(static_cast<T2>(lhs), rhs); return arithmeticCompare<T2>(static_cast<T2>(lhs), rhs);
} }
template <typename T1, typename T2> template <typename T1, typename T2>
CompareResult arithmeticCompare( CompareResult arithmeticCompare(
const T1 &lhs, const T2 &rhs, const T1 &lhs, const T2 &rhs,
typename enable_if<is_floating_point<T1>::value || typename enable_if<is_floating_point<T1>::value ||
is_floating_point<T2>::value>::type * = 0) { is_floating_point<T2>::value>::type * = 0) {
return arithmeticCompare<double>(static_cast<double>(lhs), return arithmeticCompare<double>(static_cast<double>(lhs),
static_cast<double>(rhs)); static_cast<double>(rhs));
} }
template <typename T2> template <typename T2>
CompareResult arithmeticCompareNegateLeft( CompareResult arithmeticCompareNegateLeft(
UInt, const T2 &, typename enable_if<is_unsigned<T2>::value>::type * = 0) { UInt, const T2 &, typename enable_if<is_unsigned<T2>::value>::type * = 0) {
return COMPARE_RESULT_LESS; return COMPARE_RESULT_LESS;
} }
template <typename T2> template <typename T2>
CompareResult arithmeticCompareNegateLeft( CompareResult arithmeticCompareNegateLeft(
UInt lhs, const T2 &rhs, UInt lhs, const T2 &rhs,
typename enable_if<is_signed<T2>::value>::type * = 0) { typename enable_if<is_signed<T2>::value>::type * = 0) {
if (rhs > 0) if (rhs > 0)
return COMPARE_RESULT_LESS; return COMPARE_RESULT_LESS;
return arithmeticCompare(-rhs, static_cast<T2>(lhs)); return arithmeticCompare(-rhs, static_cast<T2>(lhs));
} }
template <typename T1> template <typename T1>
CompareResult arithmeticCompareNegateRight( CompareResult arithmeticCompareNegateRight(
const T1 &, UInt, typename enable_if<is_unsigned<T1>::value>::type * = 0) { const T1 &, UInt, typename enable_if<is_unsigned<T1>::value>::type * = 0) {
return COMPARE_RESULT_GREATER; return COMPARE_RESULT_GREATER;
} }
template <typename T1> template <typename T1>
CompareResult arithmeticCompareNegateRight( CompareResult arithmeticCompareNegateRight(
const T1 &lhs, UInt rhs, const T1 &lhs, UInt rhs,
typename enable_if<is_signed<T1>::value>::type * = 0) { typename enable_if<is_signed<T1>::value>::type * = 0) {
if (lhs > 0) if (lhs > 0)
return COMPARE_RESULT_GREATER; return COMPARE_RESULT_GREATER;
return arithmeticCompare(static_cast<T1>(rhs), -lhs); return arithmeticCompare(static_cast<T1>(rhs), -lhs);
} }
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,105 +1,105 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#if defined(__clang__) #if defined(__clang__)
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion" #pragma clang diagnostic ignored "-Wconversion"
#elif defined(__GNUC__) #elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic push #pragma GCC diagnostic push
#endif #endif
#pragma GCC diagnostic ignored "-Wconversion" #pragma GCC diagnostic ignored "-Wconversion"
#endif #endif
#include <ArduinoJson/Numbers/Float.hpp> #include <ArduinoJson/Numbers/Float.hpp>
#include <ArduinoJson/Numbers/FloatTraits.hpp> #include <ArduinoJson/Numbers/FloatTraits.hpp>
#include <ArduinoJson/Numbers/Integer.hpp> #include <ArduinoJson/Numbers/Integer.hpp>
#include <ArduinoJson/Polyfills/limits.hpp> #include <ArduinoJson/Polyfills/limits.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename TOut, typename TIn> template <typename TOut, typename TIn>
typename enable_if<is_integral<TOut>::value && sizeof(TOut) <= sizeof(TIn), typename enable_if<is_integral<TOut>::value && sizeof(TOut) <= sizeof(TIn),
bool>::type bool>::type
canStorePositiveInteger(TIn value) { canStorePositiveInteger(TIn value) {
return value <= TIn(numeric_limits<TOut>::highest()); return value <= TIn(numeric_limits<TOut>::highest());
} }
template <typename TOut, typename TIn> template <typename TOut, typename TIn>
typename enable_if<is_integral<TOut>::value && sizeof(TIn) < sizeof(TOut), typename enable_if<is_integral<TOut>::value && sizeof(TIn) < sizeof(TOut),
bool>::type bool>::type
canStorePositiveInteger(TIn) { canStorePositiveInteger(TIn) {
return true; return true;
} }
template <typename TOut, typename TIn> template <typename TOut, typename TIn>
typename enable_if<is_floating_point<TOut>::value, bool>::type typename enable_if<is_floating_point<TOut>::value, bool>::type
canStorePositiveInteger(TIn) { canStorePositiveInteger(TIn) {
return true; return true;
} }
template <typename TOut, typename TIn> template <typename TOut, typename TIn>
typename enable_if<is_floating_point<TOut>::value, bool>::type typename enable_if<is_floating_point<TOut>::value, bool>::type
canStoreNegativeInteger(TIn) { canStoreNegativeInteger(TIn) {
return true; return true;
} }
template <typename TOut, typename TIn> template <typename TOut, typename TIn>
typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value && typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value &&
sizeof(TOut) <= sizeof(TIn), sizeof(TOut) <= sizeof(TIn),
bool>::type bool>::type
canStoreNegativeInteger(TIn value) { canStoreNegativeInteger(TIn value) {
return value <= TIn(numeric_limits<TOut>::highest()) + 1; return value <= TIn(numeric_limits<TOut>::highest()) + 1;
} }
template <typename TOut, typename TIn> template <typename TOut, typename TIn>
typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value && typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value &&
sizeof(TIn) < sizeof(TOut), sizeof(TIn) < sizeof(TOut),
bool>::type bool>::type
canStoreNegativeInteger(TIn) { canStoreNegativeInteger(TIn) {
return true; return true;
} }
template <typename TOut, typename TIn> template <typename TOut, typename TIn>
typename enable_if<is_integral<TOut>::value && is_unsigned<TOut>::value, typename enable_if<is_integral<TOut>::value && is_unsigned<TOut>::value,
bool>::type bool>::type
canStoreNegativeInteger(TIn) { canStoreNegativeInteger(TIn) {
return false; return false;
} }
template <typename TOut, typename TIn> template <typename TOut, typename TIn>
TOut convertPositiveInteger(TIn value) { TOut convertPositiveInteger(TIn value) {
return canStorePositiveInteger<TOut>(value) ? TOut(value) : 0; return canStorePositiveInteger<TOut>(value) ? TOut(value) : 0;
} }
template <typename TOut, typename TIn> template <typename TOut, typename TIn>
TOut convertNegativeInteger(TIn value) { TOut convertNegativeInteger(TIn value) {
return canStoreNegativeInteger<TOut>(value) ? TOut(~value + 1) : 0; return canStoreNegativeInteger<TOut>(value) ? TOut(~value + 1) : 0;
} }
template <typename TOut, typename TIn> template <typename TOut, typename TIn>
typename enable_if<is_floating_point<TOut>::value, TOut>::type convertFloat( typename enable_if<is_floating_point<TOut>::value, TOut>::type convertFloat(
TIn value) { TIn value) {
return TOut(value); return TOut(value);
} }
template <typename TOut, typename TIn> template <typename TOut, typename TIn>
typename enable_if<!is_floating_point<TOut>::value, TOut>::type convertFloat( typename enable_if<!is_floating_point<TOut>::value, TOut>::type convertFloat(
TIn value) { TIn value) {
return value >= numeric_limits<TOut>::lowest() && return value >= numeric_limits<TOut>::lowest() &&
value <= numeric_limits<TOut>::highest() value <= numeric_limits<TOut>::highest()
? TOut(value) ? TOut(value)
: 0; : 0;
} }
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE
#if defined(__clang__) #if defined(__clang__)
#pragma clang diagnostic pop #pragma clang diagnostic pop
#elif defined(__GNUC__) #elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif
#endif #endif

View File

@@ -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

View File

@@ -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

View File

@@ -1,177 +1,147 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Numbers/FloatTraits.hpp> #include <ArduinoJson/Numbers/FloatTraits.hpp>
#include <ArduinoJson/Numbers/convertNumber.hpp> #include <ArduinoJson/Numbers/convertNumber.hpp>
#include <ArduinoJson/Polyfills/assert.hpp> #include <ArduinoJson/Polyfills/assert.hpp>
#include <ArduinoJson/Polyfills/ctype.hpp> #include <ArduinoJson/Polyfills/ctype.hpp>
#include <ArduinoJson/Polyfills/math.hpp> #include <ArduinoJson/Polyfills/math.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp> #include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Variant/VariantContent.hpp> #include <ArduinoJson/Variant/VariantAs.hpp>
#include <ArduinoJson/Variant/VariantData.hpp>
namespace ARDUINOJSON_NAMESPACE {
namespace ARDUINOJSON_NAMESPACE {
template <typename TFloat, typename TUInt>
struct ParsedNumber { template <typename A, typename B>
ParsedNumber() : _type(VALUE_IS_NULL) {} struct choose_largest : conditional<(sizeof(A) > sizeof(B)), A, B> {};
void setInteger(TUInt value, bool is_negative) { inline bool parseNumber(const char* s, VariantData& result) {
uintValue = value; typedef FloatTraits<Float> traits;
_type = uint8_t(is_negative ? VALUE_IS_NEGATIVE_INTEGER typedef choose_largest<traits::mantissa_type, UInt>::type mantissa_t;
: VALUE_IS_POSITIVE_INTEGER); typedef traits::exponent_type exponent_t;
}
ARDUINOJSON_ASSERT(s != 0);
void setFloat(TFloat value) {
floatValue = value; bool is_negative = false;
_type = VALUE_IS_FLOAT; switch (*s) {
} case '-':
is_negative = true;
template <typename T> s++;
T as() const { break;
switch (_type) { case '+':
case VALUE_IS_NEGATIVE_INTEGER: s++;
return convertNegativeInteger<T>(uintValue); break;
case VALUE_IS_POSITIVE_INTEGER: }
return convertPositiveInteger<T>(uintValue);
case VALUE_IS_FLOAT: #if ARDUINOJSON_ENABLE_NAN
return convertFloat<T>(floatValue); if (*s == 'n' || *s == 'N') {
default: result.setFloat(traits::nan());
return 0; return true;
} }
} #endif
uint8_t type() const { #if ARDUINOJSON_ENABLE_INFINITY
return _type; if (*s == 'i' || *s == 'I') {
} result.setFloat(is_negative ? -traits::inf() : traits::inf());
return true;
union { }
TUInt uintValue; #endif
TFloat floatValue;
}; if (!isdigit(*s) && *s != '.')
uint8_t _type; return false;
}; // namespace ARDUINOJSON_NAMESPACE
mantissa_t mantissa = 0;
template <typename A, typename B> exponent_t exponent_offset = 0;
struct choose_largest : conditional<(sizeof(A) > sizeof(B)), A, B> {}; const mantissa_t maxUint = UInt(-1);
template <typename TFloat, typename TUInt> while (isdigit(*s)) {
inline void parseNumber(const char* s, ParsedNumber<TFloat, TUInt>& result) { uint8_t digit = uint8_t(*s - '0');
typedef FloatTraits<TFloat> traits; if (mantissa > maxUint / 10)
typedef typename choose_largest<typename traits::mantissa_type, TUInt>::type break;
mantissa_t; mantissa *= 10;
typedef typename traits::exponent_type exponent_t; if (mantissa > maxUint - digit)
break;
ARDUINOJSON_ASSERT(s != 0); mantissa += digit;
s++;
bool is_negative = false; }
switch (*s) {
case '-': if (*s == '\0') {
is_negative = true; if (is_negative)
s++; result.setNegativeInteger(UInt(mantissa));
break; else
case '+': result.setPositiveInteger(UInt(mantissa));
s++; return true;
break; }
}
// avoid mantissa overflow
#if ARDUINOJSON_ENABLE_NAN while (mantissa > traits::mantissa_max) {
if (*s == 'n' || *s == 'N') { mantissa /= 10;
result.setFloat(traits::nan()); exponent_offset++;
return; }
}
// remaing digits can't fit in the mantissa
#endif while (isdigit(*s)) {
exponent_offset++;
#if ARDUINOJSON_ENABLE_INFINITY s++;
if (*s == 'i' || *s == 'I') { }
result.setFloat(is_negative ? -traits::inf() : traits::inf());
return; if (*s == '.') {
} s++;
#endif while (isdigit(*s)) {
if (mantissa < traits::mantissa_max / 10) {
if (!isdigit(*s) && *s != '.') mantissa = mantissa * 10 + uint8_t(*s - '0');
return; exponent_offset--;
}
mantissa_t mantissa = 0; s++;
exponent_t exponent_offset = 0; }
const mantissa_t maxUint = TUInt(-1); }
while (isdigit(*s)) { int exponent = 0;
uint8_t digit = uint8_t(*s - '0'); if (*s == 'e' || *s == 'E') {
if (mantissa > maxUint / 10) s++;
break; bool negative_exponent = false;
mantissa *= 10; if (*s == '-') {
if (mantissa > maxUint - digit) negative_exponent = true;
break; s++;
mantissa += digit; } else if (*s == '+') {
s++; s++;
} }
if (*s == '\0') { while (isdigit(*s)) {
result.setInteger(TUInt(mantissa), is_negative); exponent = exponent * 10 + (*s - '0');
return; if (exponent + exponent_offset > traits::exponent_max) {
} if (negative_exponent)
result.setFloat(is_negative ? -0.0f : 0.0f);
// avoid mantissa overflow else
while (mantissa > traits::mantissa_max) { result.setFloat(is_negative ? -traits::inf() : traits::inf());
mantissa /= 10; return true;
exponent_offset++; }
} s++;
}
// remaing digits can't fit in the mantissa if (negative_exponent)
while (isdigit(*s)) { exponent = -exponent;
exponent_offset++; }
s++; exponent += exponent_offset;
}
// we should be at the end of the string, otherwise it's an error
if (*s == '.') { if (*s != '\0')
s++; return false;
while (isdigit(*s)) {
if (mantissa < traits::mantissa_max / 10) { Float final_result =
mantissa = mantissa * 10 + uint8_t(*s - '0'); traits::make_float(static_cast<Float>(mantissa), exponent);
exponent_offset--;
} result.setFloat(is_negative ? -final_result : final_result);
s++; return true;
} }
}
template <typename T>
int exponent = 0; inline T parseNumber(const char* s) {
if (*s == 'e' || *s == 'E') { VariantData value;
s++; value.init(); // VariantData is a POD, so it has no constructor
bool negative_exponent = false; parseNumber(s, value);
if (*s == '-') { return variantAs<T>(&value);
negative_exponent = true; }
s++; } // namespace ARDUINOJSON_NAMESPACE
} else if (*s == '+') {
s++;
}
while (isdigit(*s)) {
exponent = exponent * 10 + (*s - '0');
if (exponent + exponent_offset > traits::exponent_max) {
if (negative_exponent)
result.setFloat(is_negative ? -0.0f : 0.0f);
else
result.setFloat(is_negative ? -traits::inf() : traits::inf());
return;
}
s++;
}
if (negative_exponent)
exponent = -exponent;
}
exponent += exponent_offset;
// we should be at the end of the string, otherwise it's an error
if (*s != '\0')
return;
TFloat final_result =
traits::make_float(static_cast<TFloat>(mantissa), exponent);
result.setFloat(is_negative ? -final_result : final_result);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,187 +1,187 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Configuration.hpp> #include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp> #include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Variant/VariantOperators.hpp> #include <ArduinoJson/Variant/VariantOperators.hpp>
#include <ArduinoJson/Variant/VariantRef.hpp> #include <ArduinoJson/Variant/VariantRef.hpp>
#include <ArduinoJson/Variant/VariantShortcuts.hpp> #include <ArduinoJson/Variant/VariantShortcuts.hpp>
#include <ArduinoJson/Variant/VariantTo.hpp> #include <ArduinoJson/Variant/VariantTo.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4522) #pragma warning(disable : 4522)
#endif #endif
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename TObject, typename TStringRef> template <typename TObject, typename TStringRef>
class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >, class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >,
public VariantShortcuts<MemberProxy<TObject, TStringRef> >, public VariantShortcuts<MemberProxy<TObject, TStringRef> >,
public Visitable { public Visitable {
typedef MemberProxy<TObject, TStringRef> this_type; typedef MemberProxy<TObject, TStringRef> this_type;
public: public:
FORCE_INLINE MemberProxy(TObject variant, TStringRef key) FORCE_INLINE MemberProxy(TObject variant, TStringRef key)
: _object(variant), _key(key) {} : _object(variant), _key(key) {}
FORCE_INLINE MemberProxy(const MemberProxy &src) FORCE_INLINE MemberProxy(const MemberProxy &src)
: _object(src._object), _key(src._key) {} : _object(src._object), _key(src._key) {}
FORCE_INLINE operator VariantConstRef() const { FORCE_INLINE operator VariantConstRef() const {
return getUpstreamMember(); return getUpstreamMember();
} }
FORCE_INLINE this_type &operator=(const this_type &src) { FORCE_INLINE this_type &operator=(const this_type &src) {
getOrAddUpstreamMember().set(src); getOrAddUpstreamMember().set(src);
return *this; return *this;
} }
template <typename TValue> template <typename TValue>
FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type
operator=(const TValue &src) { operator=(const TValue &src) {
getOrAddUpstreamMember().set(src); getOrAddUpstreamMember().set(src);
return *this; return *this;
} }
// operator=(char*) // operator=(char*)
// operator=(const char*) // operator=(const char*)
// operator=(const __FlashStringHelper*) // operator=(const __FlashStringHelper*)
template <typename TChar> template <typename TChar>
FORCE_INLINE this_type &operator=(TChar *src) { FORCE_INLINE this_type &operator=(TChar *src) {
getOrAddUpstreamMember().set(src); getOrAddUpstreamMember().set(src);
return *this; return *this;
} }
FORCE_INLINE void clear() const { FORCE_INLINE void clear() const {
getUpstreamMember().clear(); getUpstreamMember().clear();
} }
FORCE_INLINE bool isNull() const { FORCE_INLINE bool isNull() const {
return getUpstreamMember().isNull(); return getUpstreamMember().isNull();
} }
template <typename TValue> template <typename TValue>
FORCE_INLINE typename VariantAs<TValue>::type as() const { FORCE_INLINE typename VariantAs<TValue>::type as() const {
return getUpstreamMember().template as<TValue>(); return getUpstreamMember().template as<TValue>();
} }
template <typename T> template <typename T>
FORCE_INLINE operator T() const { FORCE_INLINE operator T() const {
return getUpstreamMember(); return getUpstreamMember();
} }
template <typename TValue> template <typename TValue>
FORCE_INLINE bool is() const { FORCE_INLINE bool is() const {
return getUpstreamMember().template is<TValue>(); return getUpstreamMember().template is<TValue>();
} }
FORCE_INLINE size_t size() const { FORCE_INLINE size_t size() const {
return getUpstreamMember().size(); return getUpstreamMember().size();
} }
FORCE_INLINE void remove(size_t index) const { FORCE_INLINE void remove(size_t index) const {
getUpstreamMember().remove(index); getUpstreamMember().remove(index);
} }
// remove(char*) const // remove(char*) const
// remove(const char*) const // remove(const char*) const
// remove(const __FlashStringHelper*) const // remove(const __FlashStringHelper*) const
template <typename TChar> template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar *>::value>::type remove( FORCE_INLINE typename enable_if<IsString<TChar *>::value>::type remove(
TChar *key) const { TChar *key) const {
getUpstreamMember().remove(key); getUpstreamMember().remove(key);
} }
// remove(const std::string&) const // remove(const std::string&) const
// remove(const String&) const // remove(const String&) const
template <typename TString> template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove( FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
const TString &key) const { const TString &key) const {
getUpstreamMember().remove(key); getUpstreamMember().remove(key);
} }
template <typename TValue> template <typename TValue>
FORCE_INLINE typename VariantTo<TValue>::type to() { FORCE_INLINE typename VariantTo<TValue>::type to() {
return getOrAddUpstreamMember().template to<TValue>(); return getOrAddUpstreamMember().template to<TValue>();
} }
template <typename TValue> template <typename TValue>
FORCE_INLINE bool set(const TValue &value) { FORCE_INLINE bool set(const TValue &value) {
return getOrAddUpstreamMember().set(value); return getOrAddUpstreamMember().set(value);
} }
// set(char*) const // set(char*) const
// set(const char*) const // set(const char*) const
// set(const __FlashStringHelper*) const // set(const __FlashStringHelper*) const
template <typename TChar> template <typename TChar>
FORCE_INLINE bool set(TChar *value) { FORCE_INLINE bool set(TChar *value) {
return getOrAddUpstreamMember().set(value); return getOrAddUpstreamMember().set(value);
} }
template <typename Visitor> template <typename TVisitor>
void accept(Visitor &visitor) const { typename TVisitor::result_type accept(TVisitor &visitor) const {
return getUpstreamMember().accept(visitor); return getUpstreamMember().accept(visitor);
} }
FORCE_INLINE VariantRef addElement() const { FORCE_INLINE VariantRef addElement() const {
return getOrAddUpstreamMember().addElement(); return getOrAddUpstreamMember().addElement();
} }
FORCE_INLINE VariantRef getElement(size_t index) const { FORCE_INLINE VariantRef getElement(size_t index) const {
return getUpstreamMember().getElement(index); return getUpstreamMember().getElement(index);
} }
FORCE_INLINE VariantRef getOrAddElement(size_t index) const { FORCE_INLINE VariantRef getOrAddElement(size_t index) const {
return getOrAddUpstreamMember().getOrAddElement(index); return getOrAddUpstreamMember().getOrAddElement(index);
} }
// getMember(char*) const // getMember(char*) const
// getMember(const char*) const // getMember(const char*) const
// getMember(const __FlashStringHelper*) const // getMember(const __FlashStringHelper*) const
template <typename TChar> template <typename TChar>
FORCE_INLINE VariantRef getMember(TChar *key) const { FORCE_INLINE VariantRef getMember(TChar *key) const {
return getUpstreamMember().getMember(key); return getUpstreamMember().getMember(key);
} }
// getMember(const std::string&) const // getMember(const std::string&) const
// getMember(const String&) const // getMember(const String&) const
template <typename TString> template <typename TString>
FORCE_INLINE VariantRef getMember(const TString &key) const { FORCE_INLINE VariantRef getMember(const TString &key) const {
return getUpstreamMember().getMember(key); return getUpstreamMember().getMember(key);
} }
// getOrAddMember(char*) const // getOrAddMember(char*) const
// getOrAddMember(const char*) const // getOrAddMember(const char*) const
// getOrAddMember(const __FlashStringHelper*) const // getOrAddMember(const __FlashStringHelper*) const
template <typename TChar> template <typename TChar>
FORCE_INLINE VariantRef getOrAddMember(TChar *key) const { FORCE_INLINE VariantRef getOrAddMember(TChar *key) const {
return getOrAddUpstreamMember().getOrAddMember(key); return getOrAddUpstreamMember().getOrAddMember(key);
} }
// getOrAddMember(const std::string&) const // getOrAddMember(const std::string&) const
// getOrAddMember(const String&) const // getOrAddMember(const String&) const
template <typename TString> template <typename TString>
FORCE_INLINE VariantRef getOrAddMember(const TString &key) const { FORCE_INLINE VariantRef getOrAddMember(const TString &key) const {
return getOrAddUpstreamMember().getOrAddMember(key); return getOrAddUpstreamMember().getOrAddMember(key);
} }
private: private:
FORCE_INLINE VariantRef getUpstreamMember() const { FORCE_INLINE VariantRef getUpstreamMember() const {
return _object.getMember(_key); return _object.getMember(_key);
} }
FORCE_INLINE VariantRef getOrAddUpstreamMember() const { FORCE_INLINE VariantRef getOrAddUpstreamMember() const {
return _object.getOrAddMember(_key); return _object.getOrAddMember(_key);
} }
TObject _object; TObject _object;
TStringRef _key; TStringRef _key;
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif

View File

@@ -1,50 +1,51 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Collection/CollectionData.hpp> #include <ArduinoJson/Collection/CollectionData.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename Visitor> template <typename TVisitor>
void objectAccept(const CollectionData *obj, Visitor &visitor) { typename TVisitor::result_type objectAccept(const CollectionData *obj,
if (obj) TVisitor &visitor) {
visitor.visitObject(*obj); if (obj)
else return visitor.visitObject(*obj);
visitor.visitNull(); else
} return visitor.visitNull();
}
inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) {
if (lhs == rhs) inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) {
return true; if (lhs == rhs)
if (!lhs || !rhs) return true;
return false; if (!lhs || !rhs)
return lhs->equalsObject(*rhs); return false;
} return lhs->equalsObject(*rhs);
}
template <typename TAdaptedString>
inline VariantData *objectGetMember(const CollectionData *obj, template <typename TAdaptedString>
TAdaptedString key) { inline VariantData *objectGetMember(const CollectionData *obj,
if (!obj) TAdaptedString key) {
return 0; if (!obj)
return obj->getMember(key); return 0;
} return obj->getMember(key);
}
template <typename TAdaptedString>
void objectRemove(CollectionData *obj, TAdaptedString key) { template <typename TAdaptedString>
if (!obj) void objectRemove(CollectionData *obj, TAdaptedString key) {
return; if (!obj)
obj->removeMember(key); return;
} obj->removeMember(key);
}
template <typename TAdaptedString>
inline VariantData *objectGetOrAddMember(CollectionData *obj, template <typename TAdaptedString>
TAdaptedString key, MemoryPool *pool) { inline VariantData *objectGetOrAddMember(CollectionData *obj,
if (!obj) TAdaptedString key, MemoryPool *pool) {
return 0; if (!obj)
return 0;
return obj->getOrAddMember(key, pool);
} return obj->getOrAddMember(key, pool);
} // namespace ARDUINOJSON_NAMESPACE }
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,69 +1,69 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Array/ArrayRef.hpp> #include <ArduinoJson/Array/ArrayRef.hpp>
#include <ArduinoJson/Object/ObjectRef.hpp> #include <ArduinoJson/Object/ObjectRef.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename TObject> template <typename TObject>
template <typename TString> template <typename TString>
inline ArrayRef ObjectShortcuts<TObject>::createNestedArray( inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(
const TString& key) const { const TString& key) const {
return impl()->getOrAddMember(key).template to<ArrayRef>(); return impl()->getOrAddMember(key).template to<ArrayRef>();
} }
template <typename TObject> template <typename TObject>
template <typename TChar> template <typename TChar>
inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(TChar* key) const { inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(TChar* key) const {
return impl()->getOrAddMember(key).template to<ArrayRef>(); return impl()->getOrAddMember(key).template to<ArrayRef>();
} }
template <typename TObject> template <typename TObject>
template <typename TString> template <typename TString>
inline ObjectRef ObjectShortcuts<TObject>::createNestedObject( inline ObjectRef ObjectShortcuts<TObject>::createNestedObject(
const TString& key) const { const TString& key) const {
return impl()->getOrAddMember(key).template to<ObjectRef>(); return impl()->getOrAddMember(key).template to<ObjectRef>();
} }
template <typename TObject> template <typename TObject>
template <typename TChar> template <typename TChar>
inline ObjectRef ObjectShortcuts<TObject>::createNestedObject( inline ObjectRef ObjectShortcuts<TObject>::createNestedObject(
TChar* key) const { TChar* key) const {
return impl()->getOrAddMember(key).template to<ObjectRef>(); return impl()->getOrAddMember(key).template to<ObjectRef>();
} }
template <typename TObject> template <typename TObject>
template <typename TString> template <typename TString>
inline typename enable_if<IsString<TString>::value, bool>::type inline typename enable_if<IsString<TString>::value, bool>::type
ObjectShortcuts<TObject>::containsKey(const TString& key) const { ObjectShortcuts<TObject>::containsKey(const TString& key) const {
return !impl()->getMember(key).isUndefined(); return !impl()->getMember(key).isUndefined();
} }
template <typename TObject> template <typename TObject>
template <typename TChar> template <typename TChar>
inline typename enable_if<IsString<TChar*>::value, bool>::type inline typename enable_if<IsString<TChar*>::value, bool>::type
ObjectShortcuts<TObject>::containsKey(TChar* key) const { ObjectShortcuts<TObject>::containsKey(TChar* key) const {
return !impl()->getMember(key).isUndefined(); return !impl()->getMember(key).isUndefined();
} }
template <typename TObject> template <typename TObject>
template <typename TString> template <typename TString>
inline typename enable_if<IsString<TString*>::value, inline typename enable_if<IsString<TString*>::value,
MemberProxy<TObject, TString*> >::type MemberProxy<TObject, TString*> >::type
ObjectShortcuts<TObject>::operator[](TString* key) const { ObjectShortcuts<TObject>::operator[](TString* key) const {
return MemberProxy<TObject, TString*>(*impl(), key); return MemberProxy<TObject, TString*>(*impl(), key);
} }
template <typename TObject> template <typename TObject>
template <typename TString> template <typename TString>
inline typename enable_if<IsString<TString>::value, inline typename enable_if<IsString<TString>::value,
MemberProxy<TObject, TString> >::type MemberProxy<TObject, TString> >::type
ObjectShortcuts<TObject>::operator[](const TString& key) const { ObjectShortcuts<TObject>::operator[](const TString& key) const {
return MemberProxy<TObject, TString>(*impl(), key); return MemberProxy<TObject, TString>(*impl(), key);
} }
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,123 +1,123 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Object/Pair.hpp> #include <ArduinoJson/Object/Pair.hpp>
#include <ArduinoJson/Variant/SlotFunctions.hpp> #include <ArduinoJson/Variant/SlotFunctions.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
class PairPtr { class PairPtr {
public: public:
PairPtr(MemoryPool *pool, VariantSlot *slot) : _pair(pool, slot) {} PairPtr(MemoryPool *pool, VariantSlot *slot) : _pair(pool, slot) {}
const Pair *operator->() const { const Pair *operator->() const {
return &_pair; return &_pair;
} }
const Pair &operator*() const { const Pair &operator*() const {
return _pair; return _pair;
} }
private: private:
Pair _pair; Pair _pair;
}; };
class ObjectIterator { class ObjectIterator {
public: public:
ObjectIterator() : _slot(0) {} ObjectIterator() : _slot(0) {}
explicit ObjectIterator(MemoryPool *pool, VariantSlot *slot) explicit ObjectIterator(MemoryPool *pool, VariantSlot *slot)
: _pool(pool), _slot(slot) {} : _pool(pool), _slot(slot) {}
Pair operator*() const { Pair operator*() const {
return Pair(_pool, _slot); return Pair(_pool, _slot);
} }
PairPtr operator->() { PairPtr operator->() {
return PairPtr(_pool, _slot); return PairPtr(_pool, _slot);
} }
bool operator==(const ObjectIterator &other) const { bool operator==(const ObjectIterator &other) const {
return _slot == other._slot; return _slot == other._slot;
} }
bool operator!=(const ObjectIterator &other) const { bool operator!=(const ObjectIterator &other) const {
return _slot != other._slot; return _slot != other._slot;
} }
ObjectIterator &operator++() { ObjectIterator &operator++() {
_slot = _slot->next(); _slot = _slot->next();
return *this; return *this;
} }
ObjectIterator &operator+=(size_t distance) { ObjectIterator &operator+=(size_t distance) {
_slot = _slot->next(distance); _slot = _slot->next(distance);
return *this; return *this;
} }
VariantSlot *internal() { VariantSlot *internal() {
return _slot; return _slot;
} }
private: private:
MemoryPool *_pool; MemoryPool *_pool;
VariantSlot *_slot; VariantSlot *_slot;
}; };
class PairConstPtr { class PairConstPtr {
public: public:
PairConstPtr(const VariantSlot *slot) : _pair(slot) {} PairConstPtr(const VariantSlot *slot) : _pair(slot) {}
const PairConst *operator->() const { const PairConst *operator->() const {
return &_pair; return &_pair;
} }
const PairConst &operator*() const { const PairConst &operator*() const {
return _pair; return _pair;
} }
private: private:
PairConst _pair; PairConst _pair;
}; };
class ObjectConstIterator { class ObjectConstIterator {
public: public:
ObjectConstIterator() : _slot(0) {} ObjectConstIterator() : _slot(0) {}
explicit ObjectConstIterator(const VariantSlot *slot) : _slot(slot) {} explicit ObjectConstIterator(const VariantSlot *slot) : _slot(slot) {}
PairConst operator*() const { PairConst operator*() const {
return PairConst(_slot); return PairConst(_slot);
} }
PairConstPtr operator->() { PairConstPtr operator->() {
return PairConstPtr(_slot); return PairConstPtr(_slot);
} }
bool operator==(const ObjectConstIterator &other) const { bool operator==(const ObjectConstIterator &other) const {
return _slot == other._slot; return _slot == other._slot;
} }
bool operator!=(const ObjectConstIterator &other) const { bool operator!=(const ObjectConstIterator &other) const {
return _slot != other._slot; return _slot != other._slot;
} }
ObjectConstIterator &operator++() { ObjectConstIterator &operator++() {
_slot = _slot->next(); _slot = _slot->next();
return *this; return *this;
} }
ObjectConstIterator &operator+=(size_t distance) { ObjectConstIterator &operator+=(size_t distance) {
_slot = _slot->next(distance); _slot = _slot->next(distance);
return *this; return *this;
} }
const VariantSlot *internal() { const VariantSlot *internal() {
return _slot; return _slot;
} }
private: private:
const VariantSlot *_slot; const VariantSlot *_slot;
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,239 +1,239 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Object/ObjectFunctions.hpp> #include <ArduinoJson/Object/ObjectFunctions.hpp>
#include <ArduinoJson/Object/ObjectIterator.hpp> #include <ArduinoJson/Object/ObjectIterator.hpp>
// Returns the size (in bytes) of an object with n elements. // Returns the size (in bytes) of an object with n elements.
// Can be very handy to determine the size of a StaticMemoryPool. // Can be very handy to determine the size of a StaticMemoryPool.
#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \ #define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot)) ((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot))
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename TData> template <typename TData>
class ObjectRefBase { class ObjectRefBase {
public: public:
operator VariantConstRef() const { operator VariantConstRef() const {
const void* data = _data; // prevent warning cast-align const void* data = _data; // prevent warning cast-align
return VariantConstRef(reinterpret_cast<const VariantData*>(data)); return VariantConstRef(reinterpret_cast<const VariantData*>(data));
} }
template <typename Visitor> template <typename TVisitor>
FORCE_INLINE void accept(Visitor& visitor) const { typename TVisitor::result_type accept(TVisitor& visitor) const {
objectAccept(_data, visitor); return objectAccept(_data, visitor);
} }
FORCE_INLINE bool isNull() const { FORCE_INLINE bool isNull() const {
return _data == 0; return _data == 0;
} }
FORCE_INLINE operator bool() const { FORCE_INLINE operator bool() const {
return _data != 0; return _data != 0;
} }
FORCE_INLINE size_t memoryUsage() const { FORCE_INLINE size_t memoryUsage() const {
return _data ? _data->memoryUsage() : 0; return _data ? _data->memoryUsage() : 0;
} }
FORCE_INLINE size_t nesting() const { FORCE_INLINE size_t nesting() const {
return _data ? _data->nesting() : 0; return _data ? _data->nesting() : 0;
} }
FORCE_INLINE size_t size() const { FORCE_INLINE size_t size() const {
return _data ? _data->size() : 0; return _data ? _data->size() : 0;
} }
protected: protected:
ObjectRefBase(TData* data) : _data(data) {} ObjectRefBase(TData* data) : _data(data) {}
TData* _data; TData* _data;
}; };
class ObjectConstRef : public ObjectRefBase<const CollectionData>, class ObjectConstRef : public ObjectRefBase<const CollectionData>,
public Visitable { public Visitable {
friend class ObjectRef; friend class ObjectRef;
typedef ObjectRefBase<const CollectionData> base_type; typedef ObjectRefBase<const CollectionData> base_type;
public: public:
typedef ObjectConstIterator iterator; typedef ObjectConstIterator iterator;
ObjectConstRef() : base_type(0) {} ObjectConstRef() : base_type(0) {}
ObjectConstRef(const CollectionData* data) : base_type(data) {} ObjectConstRef(const CollectionData* data) : base_type(data) {}
FORCE_INLINE iterator begin() const { FORCE_INLINE iterator begin() const {
if (!_data) if (!_data)
return iterator(); return iterator();
return iterator(_data->head()); return iterator(_data->head());
} }
FORCE_INLINE iterator end() const { FORCE_INLINE iterator end() const {
return iterator(); return iterator();
} }
// containsKey(const std::string&) const // containsKey(const std::string&) const
// containsKey(const String&) const // containsKey(const String&) const
template <typename TString> template <typename TString>
FORCE_INLINE bool containsKey(const TString& key) const { FORCE_INLINE bool containsKey(const TString& key) const {
return !getMember(key).isUndefined(); return !getMember(key).isUndefined();
} }
// containsKey(char*) const // containsKey(char*) const
// containsKey(const char*) const // containsKey(const char*) const
// containsKey(const __FlashStringHelper*) const // containsKey(const __FlashStringHelper*) const
template <typename TChar> template <typename TChar>
FORCE_INLINE bool containsKey(TChar* key) const { FORCE_INLINE bool containsKey(TChar* key) const {
return !getMember(key).isUndefined(); return !getMember(key).isUndefined();
} }
// getMember(const std::string&) const // getMember(const std::string&) const
// getMember(const String&) const // getMember(const String&) const
template <typename TString> template <typename TString>
FORCE_INLINE VariantConstRef getMember(const TString& key) const { FORCE_INLINE VariantConstRef getMember(const TString& key) const {
return get_impl(adaptString(key)); return get_impl(adaptString(key));
} }
// getMember(char*) const // getMember(char*) const
// getMember(const char*) const // getMember(const char*) const
// getMember(const __FlashStringHelper*) const // getMember(const __FlashStringHelper*) const
template <typename TChar> template <typename TChar>
FORCE_INLINE VariantConstRef getMember(TChar* key) const { FORCE_INLINE VariantConstRef getMember(TChar* key) const {
return get_impl(adaptString(key)); return get_impl(adaptString(key));
} }
// operator[](const std::string&) const // operator[](const std::string&) const
// operator[](const String&) const // operator[](const String&) const
template <typename TString> template <typename TString>
FORCE_INLINE FORCE_INLINE
typename enable_if<IsString<TString>::value, VariantConstRef>::type typename enable_if<IsString<TString>::value, VariantConstRef>::type
operator[](const TString& key) const { operator[](const TString& key) const {
return get_impl(adaptString(key)); return get_impl(adaptString(key));
} }
// operator[](char*) const // operator[](char*) const
// operator[](const char*) const // operator[](const char*) const
// operator[](const __FlashStringHelper*) const // operator[](const __FlashStringHelper*) const
template <typename TChar> template <typename TChar>
FORCE_INLINE FORCE_INLINE
typename enable_if<IsString<TChar*>::value, VariantConstRef>::type typename enable_if<IsString<TChar*>::value, VariantConstRef>::type
operator[](TChar* key) const { operator[](TChar* key) const {
return get_impl(adaptString(key)); return get_impl(adaptString(key));
} }
FORCE_INLINE bool operator==(ObjectConstRef rhs) const { FORCE_INLINE bool operator==(ObjectConstRef rhs) const {
return objectEquals(_data, rhs._data); return objectEquals(_data, rhs._data);
} }
private: private:
template <typename TAdaptedString> template <typename TAdaptedString>
FORCE_INLINE VariantConstRef get_impl(TAdaptedString key) const { FORCE_INLINE VariantConstRef get_impl(TAdaptedString key) const {
return VariantConstRef(objectGetMember(_data, key)); return VariantConstRef(objectGetMember(_data, key));
} }
}; };
class ObjectRef : public ObjectRefBase<CollectionData>, class ObjectRef : public ObjectRefBase<CollectionData>,
public ObjectShortcuts<ObjectRef>, public ObjectShortcuts<ObjectRef>,
public Visitable { public Visitable {
typedef ObjectRefBase<CollectionData> base_type; typedef ObjectRefBase<CollectionData> base_type;
public: public:
typedef ObjectIterator iterator; typedef ObjectIterator iterator;
FORCE_INLINE ObjectRef() : base_type(0), _pool(0) {} FORCE_INLINE ObjectRef() : base_type(0), _pool(0) {}
FORCE_INLINE ObjectRef(MemoryPool* buf, CollectionData* data) FORCE_INLINE ObjectRef(MemoryPool* buf, CollectionData* data)
: base_type(data), _pool(buf) {} : base_type(data), _pool(buf) {}
operator VariantRef() const { operator VariantRef() const {
void* data = _data; // prevent warning cast-align void* data = _data; // prevent warning cast-align
return VariantRef(_pool, reinterpret_cast<VariantData*>(data)); return VariantRef(_pool, reinterpret_cast<VariantData*>(data));
} }
operator ObjectConstRef() const { operator ObjectConstRef() const {
return ObjectConstRef(_data); return ObjectConstRef(_data);
} }
FORCE_INLINE iterator begin() const { FORCE_INLINE iterator begin() const {
if (!_data) if (!_data)
return iterator(); return iterator();
return iterator(_pool, _data->head()); return iterator(_pool, _data->head());
} }
FORCE_INLINE iterator end() const { FORCE_INLINE iterator end() const {
return iterator(); return iterator();
} }
void clear() const { void clear() const {
if (!_data) if (!_data)
return; return;
_data->clear(); _data->clear();
} }
FORCE_INLINE bool set(ObjectConstRef src) { FORCE_INLINE bool set(ObjectConstRef src) {
if (!_data || !src._data) if (!_data || !src._data)
return false; return false;
return _data->copyFrom(*src._data, _pool); return _data->copyFrom(*src._data, _pool);
} }
// getMember(const std::string&) const // getMember(const std::string&) const
// getMember(const String&) const // getMember(const String&) const
template <typename TString> template <typename TString>
FORCE_INLINE VariantRef getMember(const TString& key) const { FORCE_INLINE VariantRef getMember(const TString& key) const {
return VariantRef(_pool, objectGetMember(_data, adaptString(key))); return VariantRef(_pool, objectGetMember(_data, adaptString(key)));
} }
// getMember(char*) const // getMember(char*) const
// getMember(const char*) const // getMember(const char*) const
// getMember(const __FlashStringHelper*) const // getMember(const __FlashStringHelper*) const
template <typename TChar> template <typename TChar>
FORCE_INLINE VariantRef getMember(TChar* key) const { FORCE_INLINE VariantRef getMember(TChar* key) const {
return VariantRef(_pool, objectGetMember(_data, adaptString(key))); return VariantRef(_pool, objectGetMember(_data, adaptString(key)));
} }
// getOrAddMember(const std::string&) const // getOrAddMember(const std::string&) const
// getOrAddMember(const String&) const // getOrAddMember(const String&) const
template <typename TString> template <typename TString>
FORCE_INLINE VariantRef getOrAddMember(const TString& key) const { FORCE_INLINE VariantRef getOrAddMember(const TString& key) const {
return VariantRef(_pool, return VariantRef(_pool,
objectGetOrAddMember(_data, adaptString(key), _pool)); objectGetOrAddMember(_data, adaptString(key), _pool));
} }
// getOrAddMember(char*) const // getOrAddMember(char*) const
// getOrAddMember(const char*) const // getOrAddMember(const char*) const
// getOrAddMember(const __FlashStringHelper*) const // getOrAddMember(const __FlashStringHelper*) const
template <typename TChar> template <typename TChar>
FORCE_INLINE VariantRef getOrAddMember(TChar* key) const { FORCE_INLINE VariantRef getOrAddMember(TChar* key) const {
return VariantRef(_pool, return VariantRef(_pool,
objectGetOrAddMember(_data, adaptString(key), _pool)); objectGetOrAddMember(_data, adaptString(key), _pool));
} }
FORCE_INLINE bool operator==(ObjectRef rhs) const { FORCE_INLINE bool operator==(ObjectRef rhs) const {
return objectEquals(_data, rhs._data); return objectEquals(_data, rhs._data);
} }
FORCE_INLINE void remove(iterator it) const { FORCE_INLINE void remove(iterator it) const {
if (!_data) if (!_data)
return; return;
_data->removeSlot(it.internal()); _data->removeSlot(it.internal());
} }
// remove(const std::string&) const // remove(const std::string&) const
// remove(const String&) const // remove(const String&) const
template <typename TString> template <typename TString>
FORCE_INLINE void remove(const TString& key) const { FORCE_INLINE void remove(const TString& key) const {
objectRemove(_data, adaptString(key)); objectRemove(_data, adaptString(key));
} }
// remove(char*) const // remove(char*) const
// remove(const char*) const // remove(const char*) const
// remove(const __FlashStringHelper*) const // remove(const __FlashStringHelper*) const
template <typename TChar> template <typename TChar>
FORCE_INLINE void remove(TChar* key) const { FORCE_INLINE void remove(TChar* key) const {
objectRemove(_data, adaptString(key)); objectRemove(_data, adaptString(key));
} }
private: private:
MemoryPool* _pool; MemoryPool* _pool;
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

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

View File

@@ -1,55 +1,55 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Strings/String.hpp> #include <ArduinoJson/Strings/String.hpp>
#include <ArduinoJson/Variant/VariantRef.hpp> #include <ArduinoJson/Variant/VariantRef.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
// A key value pair for CollectionData. // A key value pair for CollectionData.
class Pair { class Pair {
public: public:
Pair(MemoryPool* pool, VariantSlot* slot) { Pair(MemoryPool* pool, VariantSlot* slot) {
if (slot) { if (slot) {
_key = String(slot->key(), !slot->ownsKey()); _key = String(slot->key(), !slot->ownsKey());
_value = VariantRef(pool, slot->data()); _value = VariantRef(pool, slot->data());
} }
} }
String key() const { String key() const {
return _key; return _key;
} }
VariantRef value() const { VariantRef value() const {
return _value; return _value;
} }
private: private:
String _key; String _key;
VariantRef _value; VariantRef _value;
}; };
class PairConst { class PairConst {
public: public:
PairConst(const VariantSlot* slot) { PairConst(const VariantSlot* slot) {
if (slot) { if (slot) {
_key = String(slot->key(), !slot->ownsKey()); _key = String(slot->key(), !slot->ownsKey());
_value = VariantConstRef(slot->data()); _value = VariantConstRef(slot->data());
} }
} }
String key() const { String key() const {
return _key; return _key;
} }
VariantConstRef value() const { VariantConstRef value() const {
return _value; return _value;
} }
private: private:
String _key; String _key;
VariantConstRef _value; VariantConstRef _value;
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,29 +1,29 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> // for size_t #include <stdlib.h> // for size_t
#include <ArduinoJson/Configuration.hpp> #include <ArduinoJson/Configuration.hpp>
#include "math.hpp" #include "math.hpp"
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename T, typename F> template <typename T, typename F>
struct alias_cast_t { struct alias_cast_t {
union { union {
F raw; F raw;
T data; T data;
}; };
}; };
template <typename T, typename F> template <typename T, typename F>
T alias_cast(F raw_data) { T alias_cast(F raw_data) {
alias_cast_t<T, F> ac; alias_cast_t<T, F> ac;
ac.raw = raw_data; ac.raw = raw_data;
return ac.data; return ac.data;
} }
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,14 +1,14 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Configuration.hpp> #include <ArduinoJson/Configuration.hpp>
#if ARDUINOJSON_DEBUG #if ARDUINOJSON_DEBUG
#include <assert.h> #include <assert.h>
#define ARDUINOJSON_ASSERT(X) assert(X) #define ARDUINOJSON_ASSERT(X) assert(X)
#else #else
#define ARDUINOJSON_ASSERT(X) ((void)0) #define ARDUINOJSON_ASSERT(X) ((void)0)
#endif #endif

View File

@@ -1,45 +1,45 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#ifdef _MSC_VER // Visual Studio #ifdef _MSC_VER // Visual Studio
#define FORCE_INLINE // __forceinline causes C4714 when returning std::string #define FORCE_INLINE // __forceinline causes C4714 when returning std::string
#define NO_INLINE __declspec(noinline) #define NO_INLINE __declspec(noinline)
#define DEPRECATED(msg) __declspec(deprecated(msg)) #define DEPRECATED(msg) __declspec(deprecated(msg))
#elif defined(__GNUC__) // GCC or Clang #elif defined(__GNUC__) // GCC or Clang
#define FORCE_INLINE __attribute__((always_inline)) #define FORCE_INLINE __attribute__((always_inline))
#define NO_INLINE __attribute__((noinline)) #define NO_INLINE __attribute__((noinline))
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
#define DEPRECATED(msg) __attribute__((deprecated(msg))) #define DEPRECATED(msg) __attribute__((deprecated(msg)))
#else #else
#define DEPRECATED(msg) __attribute__((deprecated)) #define DEPRECATED(msg) __attribute__((deprecated))
#endif #endif
#else // Other compilers #else // Other compilers
#define FORCE_INLINE #define FORCE_INLINE
#define NO_INLINE #define NO_INLINE
#define DEPRECATED(msg) #define DEPRECATED(msg)
#endif #endif
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
#define NOEXCEPT noexcept #define NOEXCEPT noexcept
#else #else
#define NOEXCEPT throw() #define NOEXCEPT throw()
#endif #endif
#if defined(__has_attribute) #if defined(__has_attribute)
#if __has_attribute(no_sanitize) #if __has_attribute(no_sanitize)
#define ARDUINOJSON_NO_SANITIZE(check) __attribute__((no_sanitize(check))) #define ARDUINOJSON_NO_SANITIZE(check) __attribute__((no_sanitize(check)))
#else #else
#define ARDUINOJSON_NO_SANITIZE(check) #define ARDUINOJSON_NO_SANITIZE(check)
#endif #endif
#else #else
#define ARDUINOJSON_NO_SANITIZE(check) #define ARDUINOJSON_NO_SANITIZE(check)
#endif #endif

View File

@@ -1,18 +1,18 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
inline bool isdigit(char c) { inline bool isdigit(char c) {
return '0' <= c && c <= '9'; return '0' <= c && c <= '9';
} }
inline bool issign(char c) { inline bool issign(char c) {
return '-' == c || c == '+'; return '-' == c || c == '+';
} }
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -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

View File

@@ -1,45 +1,45 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include "type_traits.hpp" #include "type_traits.hpp"
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4310) #pragma warning(disable : 4310)
#endif #endif
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
// Differs from standard because we can't use the symbols "min" and "max" // Differs from standard because we can't use the symbols "min" and "max"
template <typename T, typename Enable = void> template <typename T, typename Enable = void>
struct numeric_limits; struct numeric_limits;
template <typename T> template <typename T>
struct numeric_limits<T, typename enable_if<is_unsigned<T>::value>::type> { struct numeric_limits<T, typename enable_if<is_unsigned<T>::value>::type> {
static T lowest() { static T lowest() {
return 0; return 0;
} }
static T highest() { static T highest() {
return T(-1); return T(-1);
} }
}; };
template <typename T> template <typename T>
struct numeric_limits< struct numeric_limits<
T, typename enable_if<is_integral<T>::value && is_signed<T>::value>::type> { T, typename enable_if<is_integral<T>::value && is_signed<T>::value>::type> {
static T lowest() { static T lowest() {
return T(T(1) << (sizeof(T) * 8 - 1)); return T(T(1) << (sizeof(T) * 8 - 1));
} }
static T highest() { static T highest() {
return T(~lowest()); return T(~lowest());
} }
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif

View File

@@ -1,27 +1,27 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
// Some libraries #define isnan() and isinf() so we need to check before // Some libraries #define isnan() and isinf() so we need to check before
// using this name // using this name
#ifndef isnan #ifndef isnan
template <typename T> template <typename T>
bool isnan(T x) { bool isnan(T x) {
return x != x; return x != x;
} }
#endif #endif
#ifndef isinf #ifndef isinf
template <typename T> template <typename T>
bool isinf(T x) { bool isinf(T x) {
return x != 0.0 && x * 2 == x; return x != 0.0 && x * 2 == x;
} }
#endif #endif
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,26 +1,26 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
#include <stddef.h> // for size_t #include <stddef.h> // for size_t
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
// A meta-function that returns the highest value // A meta-function that returns the highest value
template <size_t X, size_t Y, bool MaxIsX = (X > Y)> template <size_t X, size_t Y, bool MaxIsX = (X > Y)>
struct Max {}; struct Max {};
template <size_t X, size_t Y> template <size_t X, size_t Y>
struct Max<X, Y, true> { struct Max<X, Y, true> {
static const size_t value = X; static const size_t value = X;
}; };
template <size_t X, size_t Y> template <size_t X, size_t Y>
struct Max<X, Y, false> { struct Max<X, Y, false> {
static const size_t value = Y; static const size_t value = Y;
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,78 +1,79 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Polyfills/assert.hpp> #include <ArduinoJson/Namespace.hpp>
#include <ArduinoJson/Polyfills/assert.hpp>
namespace ARDUINOJSON_NAMESPACE {
// Wraps a const char* so that the our functions are picked only if the namespace ARDUINOJSON_NAMESPACE {
// originals are missing // Wraps a const char* so that the our functions are picked only if the
struct pgm_p { // originals are missing
pgm_p(const char* p) : address(p) {} struct pgm_p {
const char* address; pgm_p(const char* p) : address(p) {}
}; const char* address;
} // namespace ARDUINOJSON_NAMESPACE };
} // namespace ARDUINOJSON_NAMESPACE
#ifndef strlen_P
inline size_t strlen_P(ARDUINOJSON_NAMESPACE::pgm_p s) { #ifndef strlen_P
const char* p = s.address; inline size_t strlen_P(ARDUINOJSON_NAMESPACE::pgm_p s) {
ARDUINOJSON_ASSERT(p != NULL); const char* p = s.address;
while (pgm_read_byte(p)) p++; ARDUINOJSON_ASSERT(p != NULL);
return size_t(p - s.address); while (pgm_read_byte(p)) p++;
} return size_t(p - s.address);
#endif }
#endif
#ifndef strncmp_P
inline int strncmp_P(const char* a, ARDUINOJSON_NAMESPACE::pgm_p b, size_t n) { #ifndef strncmp_P
const char* s1 = a; inline int strncmp_P(const char* a, ARDUINOJSON_NAMESPACE::pgm_p b, size_t n) {
const char* s2 = b.address; const char* s1 = a;
ARDUINOJSON_ASSERT(s1 != NULL); const char* s2 = b.address;
ARDUINOJSON_ASSERT(s2 != NULL); ARDUINOJSON_ASSERT(s1 != NULL);
while (n-- > 0) { ARDUINOJSON_ASSERT(s2 != NULL);
char c1 = *s1++; while (n-- > 0) {
char c2 = static_cast<char>(pgm_read_byte(s2++)); char c1 = *s1++;
if (c1 < c2) char c2 = static_cast<char>(pgm_read_byte(s2++));
return -1; if (c1 < c2)
if (c1 > c2) return -1;
return 1; if (c1 > c2)
if (c1 == 0 /* and c2 as well */) return 1;
return 0; if (c1 == 0 /* and c2 as well */)
} return 0;
return 0; }
} return 0;
#endif }
#endif
#ifndef strcmp_P
inline int strcmp_P(const char* a, ARDUINOJSON_NAMESPACE::pgm_p b) { #ifndef strcmp_P
const char* s1 = a; inline int strcmp_P(const char* a, ARDUINOJSON_NAMESPACE::pgm_p b) {
const char* s2 = b.address; const char* s1 = a;
ARDUINOJSON_ASSERT(s1 != NULL); const char* s2 = b.address;
ARDUINOJSON_ASSERT(s2 != NULL); ARDUINOJSON_ASSERT(s1 != NULL);
for (;;) { ARDUINOJSON_ASSERT(s2 != NULL);
char c1 = *s1++; for (;;) {
char c2 = static_cast<char>(pgm_read_byte(s2++)); char c1 = *s1++;
if (c1 < c2) char c2 = static_cast<char>(pgm_read_byte(s2++));
return -1; if (c1 < c2)
if (c1 > c2) return -1;
return 1; if (c1 > c2)
if (c1 == 0 /* and c2 as well */) return 1;
return 0; if (c1 == 0 /* and c2 as well */)
} return 0;
} }
#endif }
#endif
#ifndef memcpy_P
inline void* memcpy_P(void* dst, ARDUINOJSON_NAMESPACE::pgm_p src, size_t n) { #ifndef memcpy_P
uint8_t* d = reinterpret_cast<uint8_t*>(dst); inline void* memcpy_P(void* dst, ARDUINOJSON_NAMESPACE::pgm_p src, size_t n) {
const char* s = src.address; uint8_t* d = reinterpret_cast<uint8_t*>(dst);
ARDUINOJSON_ASSERT(d != NULL); const char* s = src.address;
ARDUINOJSON_ASSERT(s != NULL); ARDUINOJSON_ASSERT(d != NULL);
while (n-- > 0) { ARDUINOJSON_ASSERT(s != NULL);
*d++ = pgm_read_byte(s++); while (n-- > 0) {
} *d++ = pgm_read_byte(s++);
return dst; }
} return dst;
#endif }
#endif

View File

@@ -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

View 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)

View File

@@ -1,32 +1,32 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
#include <stdint.h> // int8_t #include <stdint.h> // int8_t
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
inline int safe_strcmp(const char* a, const char* b) { inline int safe_strcmp(const char* a, const char* b) {
if (a == b) if (a == b)
return 0; return 0;
if (!a) if (!a)
return -1; return -1;
if (!b) if (!b)
return 1; return 1;
return strcmp(a, b); return strcmp(a, b);
} }
inline int safe_strncmp(const char* a, const char* b, size_t n) { inline int safe_strncmp(const char* a, const char* b, size_t n) {
if (a == b) if (a == b)
return 0; return 0;
if (!a) if (!a)
return -1; return -1;
if (!b) if (!b)
return 1; return 1;
return strncmp(a, b, n); return strncmp(a, b, n);
} }
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View 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

View File

@@ -1,23 +1,24 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include "type_traits/conditional.hpp" #include "type_traits/conditional.hpp"
#include "type_traits/enable_if.hpp" #include "type_traits/enable_if.hpp"
#include "type_traits/integral_constant.hpp" #include "type_traits/integral_constant.hpp"
#include "type_traits/is_array.hpp" #include "type_traits/is_array.hpp"
#include "type_traits/is_base_of.hpp" #include "type_traits/is_base_of.hpp"
#include "type_traits/is_class.hpp" #include "type_traits/is_class.hpp"
#include "type_traits/is_const.hpp" #include "type_traits/is_const.hpp"
#include "type_traits/is_convertible.hpp" #include "type_traits/is_convertible.hpp"
#include "type_traits/is_enum.hpp" #include "type_traits/is_enum.hpp"
#include "type_traits/is_floating_point.hpp" #include "type_traits/is_floating_point.hpp"
#include "type_traits/is_integral.hpp" #include "type_traits/is_integral.hpp"
#include "type_traits/is_same.hpp" #include "type_traits/is_pointer.hpp"
#include "type_traits/is_signed.hpp" #include "type_traits/is_same.hpp"
#include "type_traits/is_unsigned.hpp" #include "type_traits/is_signed.hpp"
#include "type_traits/make_unsigned.hpp" #include "type_traits/is_unsigned.hpp"
#include "type_traits/remove_const.hpp" #include "type_traits/make_unsigned.hpp"
#include "type_traits/remove_reference.hpp" #include "type_traits/remove_const.hpp"
#include "type_traits/remove_reference.hpp"

View File

@@ -1,20 +1,20 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <bool Condition, class TrueType, class FalseType> template <bool Condition, class TrueType, class FalseType>
struct conditional { struct conditional {
typedef TrueType type; typedef TrueType type;
}; };
template <class TrueType, class FalseType> template <class TrueType, class FalseType>
struct conditional<false, TrueType, FalseType> { struct conditional<false, TrueType, FalseType> {
typedef FalseType type; typedef FalseType type;
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,14 +1,14 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename T> template <typename T>
T declval(); T declval();
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,19 +1,19 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
// A meta-function that return the type T if Condition is true. // A meta-function that return the type T if Condition is true.
template <bool Condition, typename T = void> template <bool Condition, typename T = void>
struct enable_if {}; struct enable_if {};
template <typename T> template <typename T>
struct enable_if<true, T> { struct enable_if<true, T> {
typedef T type; typedef T type;
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,19 +1,19 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename T, T v> template <typename T, T v>
struct integral_constant { struct integral_constant {
static const T value = v; static const T value = v;
}; };
typedef integral_constant<bool, true> true_type; typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type; typedef integral_constant<bool, false> false_type;
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,21 +1,21 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
#include <stddef.h> // size_t #include <stddef.h> // size_t
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename T> template <typename T>
struct is_array : false_type {}; struct is_array : false_type {};
template <typename T> template <typename T>
struct is_array<T[]> : true_type {}; struct is_array<T[]> : true_type {};
template <typename T, size_t N> template <typename T, size_t N>
struct is_array<T[N]> : true_type {}; struct is_array<T[N]> : true_type {};
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,26 +1,26 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include <ArduinoJson/Namespace.hpp> #include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
// A meta-function that returns true if Derived inherits from TBase is an // A meta-function that returns true if Derived inherits from TBase is an
// integral type. // integral type.
template <typename TBase, typename TDerived> template <typename TBase, typename TDerived>
class is_base_of { class is_base_of {
protected: // <- to avoid GCC's "all member functions in class are private" protected: // <- to avoid GCC's "all member functions in class are private"
typedef char Yes[1]; typedef char Yes[1];
typedef char No[2]; typedef char No[2];
static Yes &probe(const TBase *); static Yes &probe(const TBase *);
static No &probe(...); static No &probe(...);
public: public:
static const bool value = static const bool value =
sizeof(probe(reinterpret_cast<TDerived *>(0))) == sizeof(Yes); sizeof(probe(reinterpret_cast<TDerived *>(0))) == sizeof(Yes);
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,26 +1,26 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include "declval.hpp" #include "declval.hpp"
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
template <typename T> template <typename T>
struct is_class { struct is_class {
protected: // <- to avoid GCC's "all member functions in class are private" protected: // <- to avoid GCC's "all member functions in class are private"
typedef char Yes[1]; typedef char Yes[1];
typedef char No[2]; typedef char No[2];
template <typename U> template <typename U>
static Yes &probe(void (U::*)(void)); static Yes &probe(void (U::*)(void));
template <typename> template <typename>
static No &probe(...); static No &probe(...);
public: public:
static const bool value = sizeof(probe<T>(0)) == sizeof(Yes); static const bool value = sizeof(probe<T>(0)) == sizeof(Yes);
}; };
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,17 +1,17 @@
// ArduinoJson - arduinojson.org // ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020 // Copyright Benoit Blanchon 2014-2020
// MIT License // MIT License
#pragma once #pragma once
#include "integral_constant.hpp" #include "integral_constant.hpp"
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
// A meta-function that return the type T without the const modifier // A meta-function that return the type T without the const modifier
template <typename T> template <typename T>
struct is_const : false_type {}; struct is_const : false_type {};
template <typename T> template <typename T>
struct is_const<const T> : true_type {}; struct is_const<const T> : true_type {};
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

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