forked from bblanchon/ArduinoJson
Compare commits
15 Commits
v6.5.0-bet
...
5.x
Author | SHA1 | Date | |
---|---|---|---|
46bd98fd10 | |||
63c89f166d | |||
8340b36170 | |||
ad4b13c8f0 | |||
f20f8e3171 | |||
5c297ba4a2 | |||
f483b06735 | |||
a0011ba7f8 | |||
ae2bfee0b1 | |||
b171872b58 | |||
0d01e84336 | |||
0685a36f0e | |||
ef12c74771 | |||
0bc03e8071 | |||
04286f3228 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,4 +9,3 @@
|
||||
/fuzzing/*_fuzzer
|
||||
/fuzzing/*_fuzzer.options
|
||||
/fuzzing/*_fuzzer_seed_corpus.zip
|
||||
.vs/
|
||||
|
10
.travis.yml
10
.travis.yml
@ -2,6 +2,12 @@ sudo: false
|
||||
language: cpp
|
||||
matrix:
|
||||
include:
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.4']
|
||||
env: SCRIPT=cmake GCC=4.4
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
@ -31,7 +37,7 @@ matrix:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-5']
|
||||
env: SCRIPT=cmake GCC=5 # SANITIZE=undefined
|
||||
env: SCRIPT=cmake GCC=5
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
@ -113,7 +119,7 @@ matrix:
|
||||
compiler: clang
|
||||
env: SCRIPT=cmake SANITIZE=address
|
||||
- env: SCRIPT=arduino VERSION=1.6.7 BOARD=arduino:avr:uno
|
||||
- env: SCRIPT=arduino VERSION=1.8.2 BOARD=arduino:samd:mkr1000
|
||||
- env: SCRIPT=arduino VERSION=1.8.2 BOARD=arduino:avr:uno
|
||||
- env: SCRIPT=platformio BOARD=uno
|
||||
- env: SCRIPT=platformio BOARD=esp01
|
||||
- compiler: clang
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#include "src/ArduinoJson.h"
|
||||
|
266
CHANGELOG.md
266
CHANGELOG.md
@ -1,216 +1,30 @@
|
||||
ArduinoJson: change log
|
||||
=======================
|
||||
|
||||
v6.5.0-beta (2018-10-13)
|
||||
-----------
|
||||
HEAD
|
||||
----
|
||||
|
||||
* Added implicit conversion from `JsonArray` and `JsonObject` to `JsonVariant`
|
||||
* Allow mixed configuration in compilation units (issue #809)
|
||||
* Fixed object keys not being duplicated
|
||||
* `JsonPair::key()` now returns a `JsonKey`
|
||||
* Increased the default capacity of `DynamicJsonDocument`
|
||||
* Fixed `JsonVariant::is<String>()` (closes #763)
|
||||
* Added `JsonArrayConst`, `JsonObjectConst`, and `JsonVariantConst`
|
||||
* Added copy-constructor and copy-assignment-operator for `JsonDocument` (issue #827)
|
||||
* `JsonObject::createNestedObject()` returns `JsonObject::invalid()` if key is null (issue #1891)
|
||||
* `JsonObject::createNestedArray()` returns `JsonArray::invalid()` if key is null
|
||||
|
||||
v6.4.0-beta (2018-09-11)
|
||||
-----------
|
||||
v5.13.5
|
||||
-------
|
||||
|
||||
* Copy `JsonArray` and `JsonObject`, instead of storing pointers (issue #780)
|
||||
* Added `JsonVariant::to<JsonArray>()` and `JsonVariant::to<JsonObject>()`
|
||||
* Fixed warning "unused variable" with GCC 4.4 (issue #912)
|
||||
* Fixed warning "maybe uninitialized" (issue #909)
|
||||
* Added an clear message for `StaticJsonDocument`, `DynamicJsonDocument`...
|
||||
|
||||
v6.3.0-beta (2018-08-31)
|
||||
-----------
|
||||
v5.13.4
|
||||
-------
|
||||
|
||||
* Implemented reference semantics for `JsonVariant`
|
||||
* Replaced `JsonPair`'s `key` and `value` with `key()` and `value()`
|
||||
* Fixed `serializeJson(obj[key], dst)` (issue #794)
|
||||
* Removed spurious files in the Particle library
|
||||
|
||||
> ### BREAKING CHANGES
|
||||
>
|
||||
> #### JsonVariant
|
||||
>
|
||||
> `JsonVariant` now has a semantic similar to `JsonObject` and `JsonArray`.
|
||||
> It's a reference to a value stored in the `JsonDocument`.
|
||||
> As a consequence, a `JsonVariant` cannot be used as a standalone variable anymore.
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> JsonVariant myValue = 42;
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonDocument doc;
|
||||
> JsonVariant myValue = doc.to<JsonVariant>();
|
||||
> myValue.set(42);
|
||||
> ```
|
||||
>
|
||||
> #### JsonPair
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> for(JsonPair p : myObject) {
|
||||
> Serial.println(p.key);
|
||||
> Serial.println(p.value.as<int>());
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> for(JsonPair p : myObject) {
|
||||
> Serial.println(p.key());
|
||||
> Serial.println(p.value().as<int>());
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> CAUTION: the key is now read only!
|
||||
v5.13.3
|
||||
-------
|
||||
|
||||
v6.2.3-beta (2018-07-19)
|
||||
-----------
|
||||
|
||||
* Fixed exception when using Flash strings as object keys (issue #784)
|
||||
|
||||
v6.2.2-beta (2018-07-18)
|
||||
-----------
|
||||
|
||||
* Fixed `invalid application of 'sizeof' to incomplete type '__FlashStringHelper'` (issue #783)
|
||||
* Fixed `char[]` not duplicated when passed to `JsonVariant::operator[]`
|
||||
|
||||
v6.2.1-beta (2018-07-17)
|
||||
-----------
|
||||
|
||||
* Fixed `JsonObject` not inserting keys of type `String` (issue #782)
|
||||
|
||||
v6.2.0-beta (2018-07-12)
|
||||
-----------
|
||||
|
||||
* Disabled lazy number deserialization (issue #772)
|
||||
* Fixed `JsonVariant::is<int>()` that returned true for empty strings
|
||||
* Improved float serialization when `-fsingle-precision-constant` is used
|
||||
* Renamed function `RawJson()` to `serialized()`
|
||||
* `serializeMsgPack()` now supports values marked with `serialized()`
|
||||
|
||||
> ### BREAKING CHANGES
|
||||
>
|
||||
> #### Non quoted strings
|
||||
>
|
||||
> Non quoted strings are now forbidden in values, but they are still allowed in keys.
|
||||
> For example, `{key:"value"}` is accepted, but `{key:value}` is not.
|
||||
>
|
||||
> #### Preformatted values
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> object["values"] = RawJson("[1,2,3,4]");
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> object["values"] = serialized("[1,2,3,4]");
|
||||
> ```
|
||||
|
||||
v6.1.0-beta (2018-07-02)
|
||||
-----------
|
||||
|
||||
* Return `JsonArray` and `JsonObject` by value instead of reference (issue #309)
|
||||
* Replaced `success()` with `isNull()`
|
||||
|
||||
> ### BREAKING CHANGES
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> JsonObject& obj = doc.to<JsonObject>();
|
||||
> JsonArray& arr = obj.createNestedArray("key");
|
||||
> if (!arr.success()) {
|
||||
> Serial.println("Not enough memory");
|
||||
> return;
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> JsonObject obj = doc.to<JsonObject>();
|
||||
> JsonArray arr = obj.createNestedArray("key");
|
||||
> if (arr.isNull()) {
|
||||
> Serial.println("Not enough memory");
|
||||
> return;
|
||||
> }
|
||||
> ```
|
||||
|
||||
v6.0.1-beta (2018-06-11)
|
||||
-----------
|
||||
|
||||
* Fixed conflicts with `isnan()` and `isinf()` macros (issue #752)
|
||||
|
||||
v6.0.0-beta (2018-06-07)
|
||||
-----------
|
||||
|
||||
* Added `DynamicJsonDocument` and `StaticJsonDocument`
|
||||
* Added `deserializeJson()`
|
||||
* Added `serializeJson()` and `serializeJsonPretty()`
|
||||
* Added `measureJson()` and `measureJsonPretty()`
|
||||
* Added `serializeMsgPack()`, `deserializeMsgPack()` and `measureMsgPack()` (issue #358)
|
||||
* Added example `MsgPackParser.ino` (issue #358)
|
||||
* Added support for non zero-terminated strings (issue #704)
|
||||
* Removed `JsonBuffer::parseArray()`, `parseObject()` and `parse()`
|
||||
* Removed `JsonBuffer::createArray()` and `createObject()`
|
||||
* Removed `printTo()` and `prettyPrintTo()`
|
||||
* Removed `measureLength()` and `measurePrettyLength()`
|
||||
* Removed all deprecated features
|
||||
|
||||
> ### BREAKING CHANGES
|
||||
>
|
||||
> #### Deserialization
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonBuffer jb;
|
||||
> JsonObject& obj = jb.parseObject(json);
|
||||
> if (obj.success()) {
|
||||
>
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonDocument doc;
|
||||
> DeserializationError error = deserializeJson(doc, json);
|
||||
> if (error) {
|
||||
>
|
||||
> }
|
||||
> JsonObject& obj = doc.as<JsonObject>();
|
||||
> ```
|
||||
>
|
||||
> #### Serialization
|
||||
>
|
||||
> Old code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonBuffer jb;
|
||||
> JsonObject& obj = jb.createObject();
|
||||
> obj["key"] = "value";
|
||||
> obj.printTo(Serial);
|
||||
> ```
|
||||
>
|
||||
> New code:
|
||||
>
|
||||
> ```c++
|
||||
> DynamicJsonDocument obj;
|
||||
> JsonObject& obj = doc.to<JsonObject>();
|
||||
> obj["key"] = "value";
|
||||
> serializeJson(doc, Serial);
|
||||
> ```
|
||||
* Fixed `JsonVariant::is<int>()` that returned true for empty strings
|
||||
* Fixed `JsonVariant::is<String>()` (closes #763)
|
||||
|
||||
v5.13.2
|
||||
-------
|
||||
@ -631,3 +445,51 @@ However, you should not see this as an invitation to use the `String` class.
|
||||
The `String` class is **bad** because it uses dynamic memory allocation.
|
||||
Compared to static allocation, it compiles to a bigger, slower program, and is less predictable.
|
||||
You certainly don't want that in an embedded environment!
|
||||
|
||||
v4.6
|
||||
----
|
||||
|
||||
* Fixed segmentation fault in `DynamicJsonBuffer` when memory allocation fails (issue #92)
|
||||
|
||||
v4.5
|
||||
----
|
||||
|
||||
* Fixed buffer overflow when input contains a backslash followed by a terminator (issue #81)
|
||||
|
||||
**Upgrading is recommended** since previous versions contain a potential security risk.
|
||||
|
||||
Special thanks to [Giancarlo Canales Barreto](https://github.com/gcanalesb) for finding this nasty bug.
|
||||
|
||||
v4.4
|
||||
----
|
||||
|
||||
* Added `JsonArray::measureLength()` and `JsonObject::measureLength()` (issue #75)
|
||||
|
||||
v4.3
|
||||
----
|
||||
|
||||
* Added `JsonArray::removeAt()` to remove an element of an array (issue #58)
|
||||
* Fixed stack-overflow in `DynamicJsonBuffer` when parsing huge JSON files (issue #65)
|
||||
* Fixed wrong return value of `parseArray()` and `parseObject()` when allocation fails (issue #68)
|
||||
|
||||
v4.2
|
||||
----
|
||||
|
||||
* Switched back to old library layout (issues #39, #43 and #45)
|
||||
* Removed global new operator overload (issue #40, #45 and #46)
|
||||
* Added an example with EthernetServer
|
||||
|
||||
v4.1
|
||||
----
|
||||
|
||||
* Added DynamicJsonBuffer (issue #19)
|
||||
|
||||
v4.0
|
||||
----
|
||||
|
||||
* Unified parser and generator API (issue #23)
|
||||
* Updated library layout, now requires Arduino 1.0.6 or newer
|
||||
|
||||
> ### BREAKING CHANGES :warning:
|
||||
>
|
||||
> API changed significantly since v3, see [Migrating code to the new API](https://arduinojson.org/doc/migration/).
|
||||
|
@ -1,5 +1,5 @@
|
||||
# ArduinoJson - arduinojson.org
|
||||
# Copyright Benoit Blanchon 2014-2018
|
||||
# Copyright Benoit Blanchon 2014-2019
|
||||
# MIT License
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
@ -1,7 +1,7 @@
|
||||
The MIT License (MIT)
|
||||
---------------------
|
||||
|
||||
Copyright © 2014-2018 Benoit BLANCHON
|
||||
Copyright © 2014-2019 Benoit BLANCHON
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
21
README.md
21
README.md
@ -2,7 +2,11 @@
|
||||
|
||||
---
|
||||
|
||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) [](https://travis-ci.org/bblanchon/ArduinoJson) [](https://coveralls.io/r/bblanchon/ArduinoJson?branch=6.x) [](https://github.com/bblanchon/ArduinoJson)
|
||||
[](https://www.ardu-badge.com/ArduinoJson/5.13.5)
|
||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/master)
|
||||
[](https://travis-ci.org/bblanchon/ArduinoJson)
|
||||
[](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master)
|
||||
[](https://github.com/bblanchon/ArduinoJson)
|
||||
|
||||
ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
|
||||
|
||||
@ -10,7 +14,6 @@ ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
|
||||
|
||||
* JSON decoding (comments are supported)
|
||||
* JSON encoding (with optional indentation)
|
||||
* MessagePack
|
||||
* Elegant API, easy to use
|
||||
* Fixed memory allocation (zero malloc)
|
||||
* No data duplication (zero copy)
|
||||
@ -60,10 +63,10 @@ Here is a program that parses a JSON document with ArduinoJson.
|
||||
```c++
|
||||
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
deserializeJson(doc, json);
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
|
||||
JsonObjectRef root = doc.as<JsonObject>();
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
@ -77,17 +80,17 @@ See the [tutorial on arduinojson.org](https://arduinojson.org/doc/decoding/?utm_
|
||||
Here is a program that generates a JSON document with ArduinoJson:
|
||||
|
||||
```c++
|
||||
DynamicJsonDocument doc;
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
|
||||
JsonArray data = root.createNestedArray("data");
|
||||
JsonArray& data = root.createNestedArray("data");
|
||||
data.add(48.756080);
|
||||
data.add(2.302038);
|
||||
|
||||
serializeJson(doc, Serial);
|
||||
root.printTo(Serial);
|
||||
// This prints:
|
||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
```
|
||||
|
@ -1,4 +1,4 @@
|
||||
version: 6.4.0.{build}
|
||||
version: 5.13.5.{build}
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to store your project configuration in a file.
|
||||
@ -29,19 +29,17 @@ void loadConfiguration(const char *filename, Config &config) {
|
||||
// Open file for reading
|
||||
File file = SD.open(filename);
|
||||
|
||||
// Allocate the document on the stack.
|
||||
// Don't forget to change the capacity to match your requirements.
|
||||
// Allocate the memory pool on the stack.
|
||||
// Don't forget to change the capacity to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonDocument<512> doc;
|
||||
StaticJsonBuffer<512> jsonBuffer;
|
||||
|
||||
// Deserialize the JSON document
|
||||
DeserializationError error = deserializeJson(doc, file);
|
||||
if (error)
|
||||
// Parse the root object
|
||||
JsonObject &root = jsonBuffer.parseObject(file);
|
||||
|
||||
if (!root.success())
|
||||
Serial.println(F("Failed to read file, using default configuration"));
|
||||
|
||||
// Get the root object in the document
|
||||
JsonObject root = doc.as<JsonObject>();
|
||||
|
||||
// Copy values from the JsonObject to the Config
|
||||
config.port = root["port"] | 2731;
|
||||
strlcpy(config.hostname, // <- destination
|
||||
@ -64,20 +62,20 @@ void saveConfiguration(const char *filename, const Config &config) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate the document on the stack.
|
||||
// Don't forget to change the capacity to match your requirements.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonDocument<256> doc;
|
||||
// Allocate the memory pool on the stack
|
||||
// Don't forget to change the capacity to match your JSON document.
|
||||
// Use https://arduinojson.org/assistant/ to compute the capacity.
|
||||
StaticJsonBuffer<256> jsonBuffer;
|
||||
|
||||
// Make our document contain an object
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
// Parse the root object
|
||||
JsonObject &root = jsonBuffer.createObject();
|
||||
|
||||
// Set the values in the object
|
||||
// Set the values
|
||||
root["hostname"] = config.hostname;
|
||||
root["port"] = config.port;
|
||||
|
||||
// Serialize JSON to file
|
||||
if (serializeJson(doc, file) == 0) {
|
||||
if (root.printTo(file) == 0) {
|
||||
Serial.println(F("Failed to write to file"));
|
||||
}
|
||||
|
||||
@ -132,4 +130,15 @@ void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// Visit https://arduinojson.org/v6/example/config/ for more.
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization or deserialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a case study of a project that has
|
||||
// a complex configuration with nested members.
|
||||
// Contrary to this example, the project in the book uses the SPIFFS filesystem.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to generate a JSON document with ArduinoJson.
|
||||
@ -11,20 +11,24 @@ void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial) continue;
|
||||
|
||||
// Allocate the JSON document
|
||||
// Memory pool for JSON object tree.
|
||||
//
|
||||
// Inside the brackets, 200 is the RAM allocated to this document.
|
||||
// Don't forget to change this value to match your requirement.
|
||||
// Inside the brackets, 200 is the size of the pool in bytes.
|
||||
// Don't forget to change this value to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonDocument<200> doc;
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
// StaticJsonObject allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonDocument which allocates in the heap.
|
||||
// StaticJsonBuffer allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonBuffer which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonDocument doc(200);
|
||||
// DynamicJsonBuffer jsonBuffer(200);
|
||||
|
||||
// Make our document be an object
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
// Create the root of the object tree.
|
||||
//
|
||||
// It's a reference to the JsonObject, the actual bytes are inside the
|
||||
// JsonBuffer with all the other nodes of the object tree.
|
||||
// Memory is freed when jsonBuffer goes out of scope.
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
|
||||
// Add values in the object
|
||||
//
|
||||
@ -33,19 +37,21 @@ void setup() {
|
||||
root["sensor"] = "gps";
|
||||
root["time"] = 1351824120;
|
||||
|
||||
// Add an array.
|
||||
// Add a nested array.
|
||||
//
|
||||
JsonArray data = root.createNestedArray("data");
|
||||
// It's also possible to create the array separately and add it to the
|
||||
// JsonObject but it's less efficient.
|
||||
JsonArray& data = root.createNestedArray("data");
|
||||
data.add(48.756080);
|
||||
data.add(2.302038);
|
||||
|
||||
serializeJson(root, Serial);
|
||||
root.printTo(Serial);
|
||||
// This prints:
|
||||
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||
|
||||
Serial.println();
|
||||
|
||||
serializeJsonPretty(root, Serial);
|
||||
root.prettyPrintTo(Serial);
|
||||
// This prints:
|
||||
// {
|
||||
// "sensor": "gps",
|
||||
@ -61,4 +67,15 @@ void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// Visit https://arduinojson.org/v6/example/generator/ for more.
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
||||
// It begins with a simple example, like the one above, and then adds more
|
||||
// features like serializing directly to a file or an HTTP request.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to parse a JSON document in an HTTP response.
|
||||
@ -70,21 +70,19 @@ void setup() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allocate the JSON document
|
||||
// Allocate JsonBuffer
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60;
|
||||
DynamicJsonDocument doc(capacity);
|
||||
DynamicJsonBuffer jsonBuffer(capacity);
|
||||
|
||||
// Parse JSON object
|
||||
DeserializationError error = deserializeJson(doc, client);
|
||||
if (error) {
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.c_str());
|
||||
JsonObject& root = jsonBuffer.parseObject(client);
|
||||
if (!root.success()) {
|
||||
Serial.println(F("Parsing failed!"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract values
|
||||
JsonObject root = doc.as<JsonObject>();
|
||||
Serial.println(F("Response:"));
|
||||
Serial.println(root["sensor"].as<char*>());
|
||||
Serial.println(root["time"].as<char*>());
|
||||
@ -99,4 +97,16 @@ void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// Visit https://arduinojson.org/v6/example/http-client/ for more.
|
||||
// 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 Yahoo Weather. In the last chapter,
|
||||
// it shows how to parse the huge documents from OpenWeatherMap
|
||||
// and Weather Underground.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to deserialize a JSON document with ArduinoJson.
|
||||
@ -11,17 +11,17 @@ void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial) continue;
|
||||
|
||||
// Allocate the JSON document
|
||||
// Memory pool for JSON object tree.
|
||||
//
|
||||
// Inside the brackets, 200 is the size of the memory pool in bytes.
|
||||
// Inside the brackets, 200 is the size of the pool in bytes.
|
||||
// Don't forget to change this value to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonDocument<200> doc;
|
||||
StaticJsonBuffer<200> jsonBuffer;
|
||||
|
||||
// StaticJsonDocument<N> allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonObject which allocates in the heap.
|
||||
// StaticJsonBuffer allocates memory on the stack, it can be
|
||||
// replaced by DynamicJsonBuffer which allocates in the heap.
|
||||
//
|
||||
// DynamicJsonObject doc(200);
|
||||
// DynamicJsonBuffer jsonBuffer(200);
|
||||
|
||||
// JSON input string.
|
||||
//
|
||||
@ -31,19 +31,19 @@ void setup() {
|
||||
char json[] =
|
||||
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
|
||||
// Deserialize the JSON document
|
||||
DeserializationError error = deserializeJson(doc, json);
|
||||
// Root of the object tree.
|
||||
//
|
||||
// It's a reference to the JsonObject, the actual bytes are inside the
|
||||
// JsonBuffer with all the other nodes of the object tree.
|
||||
// Memory is freed when jsonBuffer goes out of scope.
|
||||
JsonObject& root = jsonBuffer.parseObject(json);
|
||||
|
||||
// Test if parsing succeeds.
|
||||
if (error) {
|
||||
Serial.print(F("deserializeJson() failed: "));
|
||||
Serial.println(error.c_str());
|
||||
if (!root.success()) {
|
||||
Serial.println("parseObject() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the root object in the document
|
||||
JsonObject root = doc.as<JsonObject>();
|
||||
|
||||
// Fetch values.
|
||||
//
|
||||
// Most of the time, you can rely on the implicit casts.
|
||||
@ -64,4 +64,15 @@ void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// Visit https://arduinojson.org/v6/example/parser/ for more.
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// deserialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on deserialization.
|
||||
// It begins with a simple example, like the one above, and then adds more
|
||||
// features like deserializing directly from a file or an HTTP request.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to implement an HTTP server that sends JSON document
|
||||
@ -51,15 +51,15 @@ void loop() {
|
||||
// Read the request (we ignore the content in this example)
|
||||
while (client.available()) client.read();
|
||||
|
||||
// Allocate the JSON document
|
||||
// Allocate JsonBuffer
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonDocument<500> doc;
|
||||
StaticJsonBuffer<500> jsonBuffer;
|
||||
|
||||
// Make our document represent an object
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
// Create the root object
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
|
||||
// Create the "analog" array
|
||||
JsonArray analogValues = root.createNestedArray("analog");
|
||||
JsonArray& analogValues = root.createNestedArray("analog");
|
||||
for (int pin = 0; pin < 6; pin++) {
|
||||
// Read the analog input
|
||||
int value = analogRead(pin);
|
||||
@ -69,7 +69,7 @@ void loop() {
|
||||
}
|
||||
|
||||
// Create the "digital" array
|
||||
JsonArray digitalValues = root.createNestedArray("digital");
|
||||
JsonArray& digitalValues = root.createNestedArray("digital");
|
||||
for (int pin = 0; pin < 14; pin++) {
|
||||
// Read the digital input
|
||||
int value = digitalRead(pin);
|
||||
@ -79,7 +79,7 @@ void loop() {
|
||||
}
|
||||
|
||||
Serial.print(F("Sending: "));
|
||||
serializeJson(root, Serial);
|
||||
root.printTo(Serial);
|
||||
Serial.println();
|
||||
|
||||
// Write response headers
|
||||
@ -89,10 +89,21 @@ void loop() {
|
||||
client.println();
|
||||
|
||||
// Write JSON document
|
||||
serializeJsonPretty(root, client);
|
||||
root.prettyPrintTo(client);
|
||||
|
||||
// Disconnect
|
||||
client.stop();
|
||||
}
|
||||
|
||||
// Visit https://arduinojson.org/v6/example/http-server/ for more.
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
||||
// It begins with a simple example, then adds more features like serializing
|
||||
// directly to a file or an HTTP client.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to send a JSON document to a UDP socket.
|
||||
@ -43,15 +43,15 @@ void setup() {
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Allocate the JSON document
|
||||
// Allocate JsonBuffer
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
StaticJsonDocument<500> doc;
|
||||
StaticJsonBuffer<500> jsonBuffer;
|
||||
|
||||
// Make our document represent an object
|
||||
JsonObject root = doc.to<JsonObject>();
|
||||
// Create the root object
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
|
||||
// Create the "analog" array
|
||||
JsonArray analogValues = root.createNestedArray("analog");
|
||||
JsonArray& analogValues = root.createNestedArray("analog");
|
||||
for (int pin = 0; pin < 6; pin++) {
|
||||
// Read the analog input
|
||||
int value = analogRead(pin);
|
||||
@ -61,7 +61,7 @@ void loop() {
|
||||
}
|
||||
|
||||
// Create the "digital" array
|
||||
JsonArray digitalValues = root.createNestedArray("digital");
|
||||
JsonArray& digitalValues = root.createNestedArray("digital");
|
||||
for (int pin = 0; pin < 14; pin++) {
|
||||
// Read the digital input
|
||||
int value = digitalRead(pin);
|
||||
@ -75,11 +75,11 @@ void loop() {
|
||||
Serial.print(remoteIp);
|
||||
Serial.print(F(" on port "));
|
||||
Serial.println(remotePort);
|
||||
serializeJson(root, Serial);
|
||||
root.printTo(Serial);
|
||||
|
||||
// Send UDP packet
|
||||
udp.beginPacket(remoteIp, remotePort);
|
||||
serializeJson(root, udp);
|
||||
root.printTo(udp);
|
||||
udp.println();
|
||||
udp.endPacket();
|
||||
|
||||
@ -87,4 +87,15 @@ void loop() {
|
||||
delay(10000);
|
||||
}
|
||||
|
||||
// Visit https://arduinojson.org/v6/example/udp-beacon/ for more.
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any
|
||||
// serialization problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
|
||||
// It begins with a simple example, then adds more features like serializing
|
||||
// directly to a file or any stream.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,80 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
//
|
||||
// This example shows how to deserialize a MessagePack document with
|
||||
// ArduinoJson.
|
||||
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
void setup() {
|
||||
// Initialize serial port
|
||||
Serial.begin(9600);
|
||||
while (!Serial) continue;
|
||||
|
||||
// Allocate the JSON document
|
||||
//
|
||||
// Inside the brackets, 200 is the size of the memory pool in bytes.
|
||||
// Don't forget to change this value to match your JSON document.
|
||||
// Use arduinojson.org/assistant to compute the capacity.
|
||||
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.
|
||||
//
|
||||
// It's better to use a char[] as shown here.
|
||||
// If you use a const char* or a String, ArduinoJson will
|
||||
// have to make a copy of the input in the JsonBuffer.
|
||||
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]
|
||||
// }
|
||||
|
||||
// doc of the object tree.
|
||||
//
|
||||
// It's a reference to the JsonObject, the actual bytes are inside the
|
||||
// JsonBuffer with all the other nodes of the object tree.
|
||||
// Memory is freed when jsonBuffer goes out of scope.
|
||||
DeserializationError error = deserializeMsgPack(doc, input);
|
||||
|
||||
// Test if parsing succeeds.
|
||||
if (error) {
|
||||
Serial.print("deserializeMsgPack() failed: ");
|
||||
Serial.println(error.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the root object in the document
|
||||
JsonObject root = doc.as<JsonObject>();
|
||||
|
||||
// Fetch values.
|
||||
//
|
||||
// Most of the time, you can rely on the implicit casts.
|
||||
// In other case, you can do root["time"].as<long>();
|
||||
const char* sensor = root["sensor"];
|
||||
long time = root["time"];
|
||||
double latitude = root["data"][0];
|
||||
double longitude = root["data"][1];
|
||||
|
||||
// Print values.
|
||||
Serial.println(sensor);
|
||||
Serial.println(time);
|
||||
Serial.println(latitude, 6);
|
||||
Serial.println(longitude, 6);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// Visit https://arduinojson.org/v6/example/msgpack-parser/ for more.
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows the different ways you can use Flash strings with
|
||||
@ -14,35 +14,34 @@
|
||||
void setup() {
|
||||
#ifdef PROGMEM // <- check that Flash strings are supported
|
||||
|
||||
DynamicJsonDocument doc;
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
|
||||
// You can use a Flash String as your JSON input.
|
||||
// WARNING: the content of the Flash String will be duplicated in the
|
||||
// JsonBuffer.
|
||||
deserializeJson(doc, F("{\"sensor\":\"gps\",\"time\":1351824120,"
|
||||
"\"data\":[48.756080,2.302038]}"));
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
JsonObject& root =
|
||||
jsonBuffer.parseObject(F("{\"sensor\":\"gps\",\"time\":1351824120,"
|
||||
"\"data\":[48.756080,2.302038]}"));
|
||||
|
||||
// You can use a Flash String to get an element of a JsonObject
|
||||
// No duplication is done.
|
||||
long time = obj[F("time")];
|
||||
long time = root[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
|
||||
// JsonBuffer.
|
||||
obj[F("time")] = time;
|
||||
root[F("time")] = time;
|
||||
|
||||
// You can set a Flash String to a JsonObject or JsonArray:
|
||||
// WARNING: the content of the Flash String will be duplicated in the
|
||||
// JsonBuffer.
|
||||
obj["sensor"] = F("gps");
|
||||
root["sensor"] = F("gps");
|
||||
|
||||
// It works with serialized() too:
|
||||
obj["sensor"] = serialized(F("\"gps\""));
|
||||
obj["sensor"] = serialized(F("\xA3gps"), 3);
|
||||
// It works with RawJson too:
|
||||
root["sensor"] = RawJson(F("\"gps\""));
|
||||
|
||||
// You can compare the content of a JsonVariant to a Flash String
|
||||
if (obj["sensor"] == F("gps")) {
|
||||
if (root["sensor"] == F("gps")) {
|
||||
// ...
|
||||
}
|
||||
|
||||
@ -57,4 +56,15 @@ void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// Visit https://arduinojson.org/v6/example/progmem/ for more.
|
||||
// See also
|
||||
// --------
|
||||
//
|
||||
// https://arduinojson.org/ contains the documentation for all the functions
|
||||
// used above. It also includes an FAQ that will help you solve any memory
|
||||
// problem.
|
||||
//
|
||||
// The book "Mastering ArduinoJson" contains a quick C++ course that explains
|
||||
// how your microcontroller stores strings in memory. It also tells why you
|
||||
// should not abuse Flash strings with ArduinoJson.
|
||||
// Learn more at https://arduinojson.org/book/
|
||||
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
//
|
||||
// This example shows the different ways you can use String with ArduinoJson.
|
||||
@ -11,55 +11,64 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
void setup() {
|
||||
DynamicJsonDocument doc;
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
|
||||
// You can use a String as your JSON input.
|
||||
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||
String input =
|
||||
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
|
||||
deserializeJson(doc, input);
|
||||
JsonObject obj = doc.as<JsonObject>();
|
||||
JsonObject& root = jsonBuffer.parseObject(input);
|
||||
|
||||
// You can use a String to get an element of a JsonObject
|
||||
// No duplication is done.
|
||||
long time = obj[String("time")];
|
||||
long time = root[String("time")];
|
||||
|
||||
// You can use a String to set an element of a JsonObject
|
||||
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||
obj[String("time")] = time;
|
||||
root[String("time")] = time;
|
||||
|
||||
// You can get a String from a JsonObject or JsonArray:
|
||||
// No duplication is done, at least not in the JsonBuffer.
|
||||
String sensor = obj["sensor"];
|
||||
String sensor = root["sensor"];
|
||||
|
||||
// Unfortunately, the following doesn't work (issue #118):
|
||||
// sensor = obj["sensor"]; // <- error "ambiguous overload for 'operator='"
|
||||
// sensor = root["sensor"]; // <- error "ambiguous overload for 'operator='"
|
||||
// As a workaround, you need to replace by:
|
||||
sensor = obj["sensor"].as<String>();
|
||||
sensor = root["sensor"].as<String>();
|
||||
|
||||
// You can set a String to a JsonObject or JsonArray:
|
||||
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||
obj["sensor"] = sensor;
|
||||
root["sensor"] = sensor;
|
||||
|
||||
// It works with serialized() too:
|
||||
obj["sensor"] = serialized(sensor);
|
||||
// It works with RawJson too:
|
||||
root["sensor"] = RawJson(sensor);
|
||||
|
||||
// You can also concatenate strings
|
||||
// WARNING: the content of the String will be duplicated in the JsonBuffer.
|
||||
obj[String("sen") + "sor"] = String("gp") + "s";
|
||||
root[String("sen") + "sor"] = String("gp") + "s";
|
||||
|
||||
// You can compare the content of a JsonObject with a String
|
||||
if (obj["sensor"] == sensor) {
|
||||
if (root["sensor"] == sensor) {
|
||||
// ...
|
||||
}
|
||||
|
||||
// Lastly, you can print the resulting JSON to a String
|
||||
String output;
|
||||
serializeJson(doc, output);
|
||||
root.printTo(output);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// not used in this example
|
||||
}
|
||||
|
||||
// Visit https://arduinojson.org/v6/example/string/ for more.
|
||||
// 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 ❤❤❤❤❤
|
||||
|
@ -5,18 +5,15 @@ CXXFLAGS += -I../src
|
||||
all: \
|
||||
$(OUT)/json_fuzzer \
|
||||
$(OUT)/json_fuzzer_seed_corpus.zip \
|
||||
$(OUT)/json_fuzzer.options \
|
||||
$(OUT)/msgpack_fuzzer \
|
||||
$(OUT)/msgpack_fuzzer_seed_corpus.zip \
|
||||
$(OUT)/msgpack_fuzzer.options
|
||||
$(OUT)/json_fuzzer.options
|
||||
|
||||
$(OUT)/%_fuzzer: %_fuzzer.cpp $(shell find ../src -type f)
|
||||
$(OUT)/json_fuzzer: fuzzer.cpp $(shell find ../src -type f)
|
||||
$(CXX) $(CXXFLAGS) $< -o$@ $(LIB_FUZZING_ENGINE)
|
||||
|
||||
$(OUT)/%_fuzzer_seed_corpus.zip: %_seed_corpus/*
|
||||
$(OUT)/json_fuzzer_seed_corpus.zip: seed_corpus/*
|
||||
zip -j $@ $?
|
||||
|
||||
$(OUT)/%_fuzzer.options:
|
||||
$(OUT)/json_fuzzer.options:
|
||||
@echo "[libfuzzer]" > $@
|
||||
@echo "max_len = 256" >> $@
|
||||
@echo "timeout = 10" >> $@
|
||||
|
26
fuzzing/fuzzer.cpp
Normal file
26
fuzzing/fuzzer.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
class memstream : public std::istream {
|
||||
struct membuf : std::streambuf {
|
||||
membuf(const uint8_t *p, size_t l) {
|
||||
setg((char *)p, (char *)p, (char *)p + l);
|
||||
}
|
||||
};
|
||||
membuf _buffer;
|
||||
|
||||
public:
|
||||
memstream(const uint8_t *p, size_t l)
|
||||
: std::istream(&_buffer), _buffer(p, l) {
|
||||
rdbuf(&_buffer);
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
DynamicJsonBuffer jsonBuffer;
|
||||
memstream json(data, size);
|
||||
JsonVariant variant = jsonBuffer.parse(json);
|
||||
if (variant.success()) {
|
||||
variant.as<std::string>(); // <- serialize to JSON
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
DynamicJsonDocument doc;
|
||||
DeserializationError error = deserializeJson(doc, data, size);
|
||||
if (!error) {
|
||||
std::string json;
|
||||
serializeJson(doc, json);
|
||||
}
|
||||
return 0;
|
||||
}
|
2
fuzzing/msgpack_corpus/.gitignore
vendored
2
fuzzing/msgpack_corpus/.gitignore
vendored
@ -1,2 +0,0 @@
|
||||
*
|
||||
!.gitignore
|
@ -1,11 +0,0 @@
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
DynamicJsonDocument doc;
|
||||
DeserializationError error = deserializeMsgPack(doc, data, size);
|
||||
if (!error) {
|
||||
std::string json;
|
||||
serializeMsgPack(doc, json);
|
||||
}
|
||||
return 0;
|
||||
}
|
Binary file not shown.
Binary file not shown.
@ -1 +0,0 @@
|
||||
<EFBFBD>
|
@ -1 +0,0 @@
|
||||
<EFBFBD><EFBFBD>hello<EFBFBD>world
|
@ -1 +0,0 @@
|
||||
<EFBFBD>
|
@ -1 +0,0 @@
|
||||
|
@ -1 +0,0 @@
|
||||
<EFBFBD><EFBFBD>one<01>two
|
@ -1 +0,0 @@
|
||||
<EFBFBD>hello world
|
@ -1 +0,0 @@
|
||||
<EFBFBD>@H<><48>
|
@ -1 +0,0 @@
|
||||
<EFBFBD>@ !<21><><EFBFBD>o
|
@ -1 +0,0 @@
|
||||
<EFBFBD><EFBFBD><EFBFBD>
|
@ -1 +0,0 @@
|
||||
Ҷi<EFBFBD>.
|
@ -1 +0,0 @@
|
||||
<EFBFBD>4Vx<56><78><EFBFBD><EFBFBD>
|
@ -1 +0,0 @@
|
||||
<EFBFBD><EFBFBD>
|
Binary file not shown.
Binary file not shown.
@ -1 +0,0 @@
|
||||
<EFBFBD>
|
Binary file not shown.
Binary file not shown.
@ -1 +0,0 @@
|
||||
<EFBFBD>hello
|
@ -1 +0,0 @@
|
||||
<EFBFBD>
|
@ -1 +0,0 @@
|
||||
<EFBFBD>09
|
@ -1 +0,0 @@
|
||||
<EFBFBD>4Vx
|
@ -1 +0,0 @@
|
||||
<EFBFBD>4Vx<56><78><EFBFBD><EFBFBD>
|
@ -1 +0,0 @@
|
||||
<EFBFBD><EFBFBD>
|
26
keywords.txt
26
keywords.txt
@ -1,17 +1,15 @@
|
||||
add KEYWORD2
|
||||
as KEYWORD2
|
||||
createNestedArray KEYWORD2
|
||||
createNestedObject KEYWORD2
|
||||
deserializeJson KEYWORD2
|
||||
deserializeMsgPack KEYWORD2
|
||||
DynamicJsonDocument KEYWORD1
|
||||
get KEYWORD2
|
||||
JsonArray KEYWORD1
|
||||
JsonObject KEYWORD1
|
||||
JsonVariant KEYWORD1
|
||||
serializeMsgPack KEYWORD2
|
||||
serializeJson KEYWORD2
|
||||
serializeJsonPretty KEYWORD2
|
||||
set KEYWORD2
|
||||
StaticJsonDocument KEYWORD1
|
||||
to KEYWORD2
|
||||
StaticJsonBuffer KEYWORD1
|
||||
DynamicJsonBuffer KEYWORD1
|
||||
add KEYWORD2
|
||||
createArray KEYWORD2
|
||||
createNestedArray KEYWORD2
|
||||
createNestedObject KEYWORD2
|
||||
createObject KEYWORD2
|
||||
parseArray KEYWORD2
|
||||
parseObject KEYWORD2
|
||||
prettyPrintTo KEYWORD2
|
||||
printTo KEYWORD2
|
||||
success KEYWORD2
|
||||
|
@ -7,7 +7,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/bblanchon/ArduinoJson.git"
|
||||
},
|
||||
"version": "6.5.0-beta",
|
||||
"version": "5.13.5",
|
||||
"authors": {
|
||||
"name": "Benoit Blanchon",
|
||||
"url": "https://blog.benoitblanchon.fr"
|
||||
|
@ -1,9 +1,9 @@
|
||||
name=ArduinoJson
|
||||
version=6.5.0-beta
|
||||
version=5.13.5
|
||||
author=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
sentence=An efficient and elegant JSON library for Arduino.
|
||||
paragraph=ArduinoJson supports ✔ serialization, ✔ deserialization, ✔ MessagePack, ✔ fixed allocation, ✔ zero-copy, ✔ streams, and more. It is the most popular Arduino library on GitHub ❤❤❤❤❤. Check out arduinojson.org for a comprehensive documentation.
|
||||
paragraph=ArduinoJson supports ✔ serialization, ✔ deserialization, ✔ fixed allocation, ✔ zero-copy, ✔ streams, 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=*
|
||||
|
@ -1,42 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -eu
|
||||
|
||||
OUTPUT="$(pwd)/sizes.csv"
|
||||
|
||||
echo "Tag;Date;Parser;Generator" > $OUTPUT
|
||||
|
||||
cd $(dirname $(dirname $0))
|
||||
|
||||
git tag | while read TAG
|
||||
do
|
||||
|
||||
git checkout -q tags/$TAG
|
||||
|
||||
DATE=$(git log -1 --date=short --pretty=format:%cd)
|
||||
PARSER_SIZE=$(arduino --verify examples/JsonParserExample/JsonParserExample.ino 2>/dev/null | grep -e 'Sketch uses' | sed 's/.*uses \([0-9]*\).\([0-9]\+\).*/\1\2/')
|
||||
|
||||
if [ -e 'examples/JsonGeneratorExample/JsonGeneratorExample.ino' ]; then
|
||||
GENERATOR_SIZE=$(arduino --verify examples/JsonGeneratorExample/JsonGeneratorExample.ino 2>/dev/null | grep -e 'Sketch uses' | sed 's/.*uses \([0-9]*\).\([0-9]\+\).*/\1\2/')
|
||||
else
|
||||
GENERATOR_SIZE=""
|
||||
fi
|
||||
|
||||
echo $TAG
|
||||
if [ ! -z "$PARSER_SIZE" ]
|
||||
then
|
||||
echo "JsonParserExample = $PARSER_SIZE bytes"
|
||||
else
|
||||
echo "JsonParserExample compilation failed."
|
||||
fi
|
||||
|
||||
if [ ! -z "$GENERATOR_SIZE" ]
|
||||
then
|
||||
echo "JsonGeneratorExample = $GENERATOR_SIZE bytes"
|
||||
else
|
||||
echo "JsonGeneratorExample compilation failed."
|
||||
fi
|
||||
|
||||
echo "$TAG;$DATE;$PARSER_SIZE;$GENERATOR_SIZE" >> $OUTPUT
|
||||
|
||||
done
|
11
scripts/oss-fuzz/Vagrantfile
vendored
11
scripts/oss-fuzz/Vagrantfile
vendored
@ -2,16 +2,11 @@
|
||||
Vagrant.configure(2) do |config|
|
||||
config.vm.box = "ubuntu/xenial64"
|
||||
|
||||
config.vm.synced_folder "../..", "/host/ArduinoJson"
|
||||
config.vm.synced_folder "E:\\Git\\Arduino\\libraries\\ArduinoJson", "/host/ArduinoJson"
|
||||
config.vm.synced_folder "E:\\Git\\oss-fuzz", "/host/oss-fuzz"
|
||||
|
||||
config.vm.network "forwarded_port", guest: 8001, host: 8001
|
||||
|
||||
config.vm.provider "virtualbox" do |v|
|
||||
v.memory = 2048
|
||||
v.cpus = 2
|
||||
end
|
||||
|
||||
config.vm.provision "shell", privileged: false, inline: <<-SHELL
|
||||
set -x
|
||||
|
||||
@ -23,6 +18,10 @@ Vagrant.configure(2) do |config|
|
||||
git clone https://github.com/google/fuzzer-test-suite.git FTS
|
||||
./FTS/tutorial/install-deps.sh # Get deps
|
||||
./FTS/tutorial/install-clang.sh # Get fresh clang binaries
|
||||
# Get libFuzzer sources and build it
|
||||
svn co http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer
|
||||
Fuzzer/build.sh
|
||||
sudo mv libFuzzer.a /usr/local/lib/
|
||||
|
||||
echo "export PROJECT_NAME='arduinojson'" >> $HOME/.profile
|
||||
echo "export CC='clang'" >> $HOME/.profile
|
||||
|
18
scripts/publish-particle-library.sh
Normal file
18
scripts/publish-particle-library.sh
Normal file
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
|
||||
SOURCE_DIR="$(dirname "$0")/.."
|
||||
WORK_DIR=$(mktemp -d)
|
||||
trap 'rm -rf "$WORK_DIR"' EXIT
|
||||
|
||||
cp "$SOURCE_DIR/README.md" "$WORK_DIR/README.md"
|
||||
cp "$SOURCE_DIR/CHANGELOG.md" "$WORK_DIR/CHANGELOG.md"
|
||||
cp "$SOURCE_DIR/library.properties" "$WORK_DIR/library.properties"
|
||||
cp "$SOURCE_DIR/LICENSE.md" "$WORK_DIR/LICENSE.txt"
|
||||
cp -r "$SOURCE_DIR/src" "$WORK_DIR/"
|
||||
cp -r "$SOURCE_DIR/examples" "$WORK_DIR/"
|
||||
|
||||
cd "$WORK_DIR"
|
||||
particle library upload
|
||||
particle library publish
|
@ -1,49 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
VERSION="$1"
|
||||
DATE=$(date +%F)
|
||||
TAG="v$VERSION"
|
||||
|
||||
update_version_in_source () {
|
||||
IFS=".-" read MAJOR MINOR REVISION EXTRA < <(echo "$VERSION")
|
||||
UNDERLINE=$(printf -- '-%.0s' $(seq 1 ${#TAG}))
|
||||
|
||||
sed -i~ -bE "4s/HEAD/$TAG ($DATE)/; 5s/-+/$UNDERLINE/" CHANGELOG.md
|
||||
rm CHANGELOG.md*~
|
||||
sed -i~ -bE "s/\"version\":.*$/\"version\": \"$VERSION\",/" library.json
|
||||
rm library.json*~
|
||||
|
||||
sed -i~ -bE "s/version=.*$/version=$VERSION/" library.properties
|
||||
rm library.properties*~
|
||||
|
||||
sed -i~ -bE \
|
||||
-e "s/ARDUINOJSON_VERSION .*$/ARDUINOJSON_VERSION \"$VERSION\"/" \
|
||||
-e "s/ARDUINOJSON_VERSION_MAJOR .*$/ARDUINOJSON_VERSION_MAJOR $MAJOR/" \
|
||||
-e "s/ARDUINOJSON_VERSION_MINOR .*$/ARDUINOJSON_VERSION_MINOR $MINOR/" \
|
||||
-e "s/ARDUINOJSON_VERSION_REVISION .*$/ARDUINOJSON_VERSION_REVISION $REVISION/" \
|
||||
src/ArduinoJson/version.hpp
|
||||
rm src/ArduinoJson/version.hpp*~
|
||||
}
|
||||
|
||||
commit_new_version () {
|
||||
git add src/ArduinoJson/version.hpp CHANGELOG.md library.json library.properties
|
||||
git commit -m "Set version to $VERSION"
|
||||
}
|
||||
|
||||
add_tag () {
|
||||
CHANGES=$(awk '/\* /{ FOUND=1; print; next } { if (FOUND) exit}' CHANGELOG.md)
|
||||
git tag -m "ArduinoJson $VERSION"$'\n'"$CHANGES" "$TAG"
|
||||
}
|
||||
|
||||
push () {
|
||||
git push --follow-tags
|
||||
}
|
||||
|
||||
update_version_in_source
|
||||
commit_new_version
|
||||
add_tag
|
||||
push
|
@ -1,4 +1,4 @@
|
||||
#!/bin/bash -eux
|
||||
#!/bin/sh -eux
|
||||
|
||||
/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16
|
||||
sleep 3
|
||||
@ -6,13 +6,9 @@ export DISPLAY=:1.0
|
||||
|
||||
mkdir -p /tmp/arduino
|
||||
curl -sS http://downloads.arduino.cc/arduino-$VERSION-linux64.tar.xz | tar xJ -C /tmp/arduino --strip 1 ||
|
||||
curl -sS http://downloads.arduino.cc/arduino-$VERSION-linux64.tgz | tar xz -C /tmp/arduino --strip 1
|
||||
curl -sS http://downloads.arduino.cc/arduino-$VERSION-linux64.tgz | tar xz -C /tmp/arduino --strip 1
|
||||
export PATH=$PATH:/tmp/arduino/
|
||||
|
||||
if [[ "$BOARD" =~ "arduino:samd:" ]]; then
|
||||
arduino --install-boards arduino:samd
|
||||
fi
|
||||
|
||||
|
||||
ln -s $PWD /tmp/arduino/libraries/ArduinoJson
|
||||
|
||||
for EXAMPLE in $PWD/examples/*/*.ino; do
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/sh -ex
|
||||
|
||||
if [ $(uname) = 'Darwin' ]; then
|
||||
if [ "$(uname)" = 'Darwin' ]; then
|
||||
URL=https://cmake.org/files/v3.4/cmake-3.4.3-Darwin-x86_64.tar.gz
|
||||
CMAKE=/tmp/CMake.app/Contents/bin/cmake
|
||||
CTEST=/tmp/CMake.app/Contents/bin/ctest
|
||||
@ -23,8 +23,11 @@ fi
|
||||
|
||||
if [ -n "$SANITIZE" ]; then
|
||||
export CXXFLAGS="-fsanitize=$SANITIZE"
|
||||
BUILD_TYPE="Debug"
|
||||
else
|
||||
BUILD_TYPE="Release"
|
||||
fi
|
||||
|
||||
$CMAKE .
|
||||
$CMAKE -DCMAKE_BUILD_TYPE=$BUILD_TYPE .
|
||||
$CMAKE --build .
|
||||
$CTEST --output-on-failure .
|
||||
|
@ -1,26 +1,20 @@
|
||||
#!/bin/bash -eux
|
||||
|
||||
ROOT_DIR=$(dirname $0)/../../
|
||||
INCLUDE_DIR=${ROOT_DIR}/src/
|
||||
FUZZING_DIR=${ROOT_DIR}/fuzzing/
|
||||
INCLUDE_DIR=$ROOT_DIR/src/
|
||||
FUZZING_DIR=$ROOT_DIR/fuzzing/
|
||||
JSON_CORPUS_DIR=$FUZZING_DIR/my_corpus
|
||||
JSON_SEED_CORPUS_DIR=$FUZZING_DIR/seed_corpus
|
||||
|
||||
CXX="clang++-$CLANG"
|
||||
CXXFLAGS="-g -fprofile-instr-generate -fcoverage-mapping -fsanitize=address,fuzzer"
|
||||
|
||||
fuzz() {
|
||||
NAME="$1"
|
||||
FUZZER="${NAME}_fuzzer"
|
||||
FUZZER_CPP="${FUZZING_DIR}/${NAME}_fuzzer.cpp"
|
||||
CORPUS_DIR="${FUZZING_DIR}/${NAME}_corpus"
|
||||
SEED_CORPUS_DIR="${FUZZING_DIR}/${NAME}_seed_corpus"
|
||||
$CXX $CXXFLAGS -o json_fuzzer -I$INCLUDE_DIR $FUZZING_DIR/fuzzer.cpp
|
||||
|
||||
clang++-${CLANG} ${CXXFLAGS} -o ${FUZZER} -I$INCLUDE_DIR ${FUZZER_CPP}
|
||||
export ASAN_OPTIONS="detect_leaks=0"
|
||||
export LLVM_PROFILE_FILE="json_fuzzer.profraw"
|
||||
./json_fuzzer "$JSON_CORPUS_DIR" "$JSON_SEED_CORPUS_DIR" -max_total_time=60
|
||||
|
||||
export ASAN_OPTIONS="detect_leaks=0"
|
||||
export LLVM_PROFILE_FILE="${FUZZER}.profraw"
|
||||
./${FUZZER} "$CORPUS_DIR" "$SEED_CORPUS_DIR" -max_total_time=30
|
||||
llvm-profdata-$CLANG merge -sparse json_fuzzer.profraw -o json_fuzzer.profdata
|
||||
|
||||
llvm-profdata-${CLANG} merge -sparse ${LLVM_PROFILE_FILE} -o ${FUZZER}.profdata
|
||||
llvm-cov-${CLANG} report ./${FUZZER} -instr-profile=${FUZZER}.profdata
|
||||
}
|
||||
|
||||
fuzz json
|
||||
fuzz msgpack
|
||||
llvm-cov-$CLANG report ./json_fuzzer -instr-profile=json_fuzzer.profdata
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
@ -1,43 +1,21 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ArduinoJson/Namespace.hpp"
|
||||
#include "ArduinoJson/version.hpp"
|
||||
|
||||
#include "ArduinoJson/DynamicJsonBuffer.hpp"
|
||||
#include "ArduinoJson/JsonArray.hpp"
|
||||
#include "ArduinoJson/JsonDocument.hpp"
|
||||
#include "ArduinoJson/JsonObject.hpp"
|
||||
#include "ArduinoJson/JsonVariant.hpp"
|
||||
#include "ArduinoJson/StaticJsonBuffer.hpp"
|
||||
|
||||
#include "ArduinoJson/Data/VariantAsImpl.hpp"
|
||||
#include "ArduinoJson/Deserialization/JsonParserImpl.hpp"
|
||||
#include "ArduinoJson/JsonArrayImpl.hpp"
|
||||
#include "ArduinoJson/JsonArraySubscript.hpp"
|
||||
#include "ArduinoJson/JsonBufferImpl.hpp"
|
||||
#include "ArduinoJson/JsonObjectImpl.hpp"
|
||||
#include "ArduinoJson/JsonObjectSubscript.hpp"
|
||||
#include "ArduinoJson/JsonVariantImpl.hpp"
|
||||
#include "ArduinoJson/Serialization/JsonSerializerImpl.hpp"
|
||||
|
||||
#include "ArduinoJson/Json/JsonDeserializer.hpp"
|
||||
#include "ArduinoJson/Json/JsonSerializer.hpp"
|
||||
#include "ArduinoJson/Json/PrettyJsonSerializer.hpp"
|
||||
#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
|
||||
#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
using ARDUINOJSON_NAMESPACE::DeserializationError;
|
||||
using ARDUINOJSON_NAMESPACE::DynamicJsonDocument;
|
||||
using ARDUINOJSON_NAMESPACE::JsonArray;
|
||||
using ARDUINOJSON_NAMESPACE::JsonArrayConst;
|
||||
using ARDUINOJSON_NAMESPACE::JsonFloat;
|
||||
using ARDUINOJSON_NAMESPACE::JsonInteger;
|
||||
using ARDUINOJSON_NAMESPACE::JsonKey;
|
||||
using ARDUINOJSON_NAMESPACE::JsonObject;
|
||||
using ARDUINOJSON_NAMESPACE::JsonObjectConst;
|
||||
using ARDUINOJSON_NAMESPACE::JsonPair;
|
||||
using ARDUINOJSON_NAMESPACE::JsonUInt;
|
||||
using ARDUINOJSON_NAMESPACE::JsonVariant;
|
||||
using ARDUINOJSON_NAMESPACE::JsonVariantConst;
|
||||
using ARDUINOJSON_NAMESPACE::serialized;
|
||||
using ARDUINOJSON_NAMESPACE::StaticJsonDocument;
|
||||
} // namespace ArduinoJson
|
||||
#include "ArduinoJson/compatibility.hpp"
|
||||
|
@ -1,21 +1,9 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define ARDUINOJSON_HAS_INT64 1
|
||||
#else
|
||||
#define ARDUINOJSON_HAS_INT64 0
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#define ARDUINOJSON_HAS_LONG_LONG 1
|
||||
#else
|
||||
#define ARDUINOJSON_HAS_LONG_LONG 0
|
||||
#endif
|
||||
|
||||
// Small or big machine?
|
||||
#ifndef ARDUINOJSON_EMBEDDED_MODE
|
||||
#if defined(ARDUINO) || defined(__IAR_SYSTEMS_ICC__) || defined(__XC) || \
|
||||
@ -37,6 +25,9 @@
|
||||
#ifndef ARDUINOJSON_USE_LONG_LONG
|
||||
#define ARDUINOJSON_USE_LONG_LONG 0
|
||||
#endif
|
||||
#ifndef ARDUINOJSON_USE_INT64
|
||||
#define ARDUINOJSON_USE_INT64 0
|
||||
#endif
|
||||
|
||||
// Embedded systems usually don't have std::string
|
||||
#ifndef ARDUINOJSON_ENABLE_STD_STRING
|
||||
@ -53,11 +44,6 @@
|
||||
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 10
|
||||
#endif
|
||||
|
||||
// Default capacity for DynamicJsonDocument
|
||||
#ifndef ARDUINOJSON_DEFAULT_POOL_SIZE
|
||||
#define ARDUINOJSON_DEFAULT_POOL_SIZE 1024
|
||||
#endif
|
||||
|
||||
#else // ARDUINOJSON_EMBEDDED_MODE
|
||||
|
||||
// On a computer we have plenty of memory so we can use doubles
|
||||
@ -67,13 +53,22 @@
|
||||
|
||||
// Use long long when available
|
||||
#ifndef ARDUINOJSON_USE_LONG_LONG
|
||||
#if ARDUINOJSON_HAS_LONG_LONG || ARDUINOJSON_HAS_INT64
|
||||
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
|
||||
#define ARDUINOJSON_USE_LONG_LONG 1
|
||||
#else
|
||||
#define ARDUINOJSON_USE_LONG_LONG 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Use _int64 on old versions of Visual Studio
|
||||
#ifndef ARDUINOJSON_USE_INT64
|
||||
#if defined(_MSC_VER) && _MSC_VER <= 1700
|
||||
#define ARDUINOJSON_USE_INT64 1
|
||||
#else
|
||||
#define ARDUINOJSON_USE_INT64 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// On a computer, we can use std::string
|
||||
#ifndef ARDUINOJSON_ENABLE_STD_STRING
|
||||
#define ARDUINOJSON_ENABLE_STD_STRING 1
|
||||
@ -89,11 +84,6 @@
|
||||
#define ARDUINOJSON_DEFAULT_NESTING_LIMIT 50
|
||||
#endif
|
||||
|
||||
// Default capacity for DynamicJsonDocument
|
||||
#ifndef ARDUINOJSON_DEFAULT_POOL_SIZE
|
||||
#define ARDUINOJSON_DEFAULT_POOL_SIZE 16384
|
||||
#endif
|
||||
|
||||
#endif // ARDUINOJSON_EMBEDDED_MODE
|
||||
|
||||
#ifdef ARDUINO
|
||||
@ -140,6 +130,11 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Enable deprecated functions by default
|
||||
#ifndef ARDUINOJSON_ENABLE_DEPRECATED
|
||||
#define ARDUINOJSON_ENABLE_DEPRECATED 1
|
||||
#endif
|
||||
|
||||
// Control the exponentiation threshold for big numbers
|
||||
// CAUTION: cannot be more that 1e9 !!!!
|
||||
#ifndef ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD
|
||||
@ -151,12 +146,6 @@
|
||||
#define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINOJSON_LITTLE_ENDIAN
|
||||
#if defined(_MSC_VER) || \
|
||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
|
||||
(defined(__LITTLE_ENDIAN__))
|
||||
#define ARDUINOJSON_LITTLE_ENDIAN 1
|
||||
#else
|
||||
#define ARDUINOJSON_LITTLE_ENDIAN 0
|
||||
#endif
|
||||
#if ARDUINOJSON_USE_LONG_LONG && ARDUINOJSON_USE_INT64
|
||||
#error ARDUINOJSON_USE_LONG_LONG and ARDUINOJSON_USE_INT64 cannot be set together
|
||||
#endif
|
||||
|
@ -1,99 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariantData.hpp"
|
||||
#include "Slot.hpp"
|
||||
#include "SlotFunctions.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
inline JsonVariantData* arrayAdd(JsonArrayData* arr, MemoryPool* pool) {
|
||||
if (!arr) return 0;
|
||||
|
||||
Slot* slot = new (pool) Slot();
|
||||
if (!slot) return 0;
|
||||
|
||||
slot->next = 0;
|
||||
|
||||
if (arr->tail) {
|
||||
slot->prev = arr->tail;
|
||||
arr->tail->next = slot;
|
||||
arr->tail = slot;
|
||||
} else {
|
||||
slot->prev = 0;
|
||||
arr->head = slot;
|
||||
arr->tail = slot;
|
||||
}
|
||||
|
||||
return &slot->value;
|
||||
}
|
||||
|
||||
inline Slot* arrayGetSlot(const JsonArrayData* arr, size_t index) {
|
||||
if (!arr) return 0;
|
||||
return slotAdvance(arr->head, index);
|
||||
}
|
||||
|
||||
inline JsonVariantData* arrayGet(const JsonArrayData* arr, size_t index) {
|
||||
Slot* slot = arrayGetSlot(arr, index);
|
||||
return slot ? &slot->value : 0;
|
||||
}
|
||||
|
||||
inline void arrayRemove(JsonArrayData* arr, Slot* slot) {
|
||||
if (!arr || !slot) return;
|
||||
|
||||
if (slot->prev)
|
||||
slot->prev->next = slot->next;
|
||||
else
|
||||
arr->head = slot->next;
|
||||
if (slot->next)
|
||||
slot->next->prev = slot->prev;
|
||||
else
|
||||
arr->tail = slot->prev;
|
||||
}
|
||||
|
||||
inline void arrayRemove(JsonArrayData* arr, size_t index) {
|
||||
arrayRemove(arr, arrayGetSlot(arr, index));
|
||||
}
|
||||
|
||||
inline void arrayClear(JsonArrayData* arr) {
|
||||
if (!arr) return;
|
||||
arr->head = 0;
|
||||
arr->tail = 0;
|
||||
}
|
||||
|
||||
bool variantCopy(JsonVariantData*, const JsonVariantData*, MemoryPool*);
|
||||
|
||||
inline bool arrayCopy(JsonArrayData* dst, const JsonArrayData* src,
|
||||
MemoryPool* pool) {
|
||||
if (!dst || !src) return false;
|
||||
arrayClear(dst);
|
||||
for (Slot* s = src->head; s; s = s->next) {
|
||||
if (!variantCopy(arrayAdd(dst, pool), &s->value, pool)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool variantEquals(const JsonVariantData*, const JsonVariantData*);
|
||||
|
||||
inline bool arrayEquals(const JsonArrayData* a1, const JsonArrayData* a2) {
|
||||
if (a1 == a2) return true;
|
||||
if (!a1 || !a2) return false;
|
||||
Slot* s1 = a1->head;
|
||||
Slot* s2 = a2->head;
|
||||
for (;;) {
|
||||
if (s1 == s2) return true;
|
||||
if (!s1 || !s2) return false;
|
||||
if (!variantEquals(&s1->value, &s2->value)) return false;
|
||||
s1 = s1->next;
|
||||
s2 = s2->next;
|
||||
}
|
||||
}
|
||||
|
||||
inline size_t arraySize(const JsonArrayData* arr) {
|
||||
if (!arr) return 0;
|
||||
return slotSize(arr->head);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,12 +1,13 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
class EscapeSequence {
|
||||
class Encoding {
|
||||
public:
|
||||
// Optimized for code size on a 8-bit AVR
|
||||
static char escapeChar(char c) {
|
||||
@ -32,4 +33,5 @@ class EscapeSequence {
|
||||
return &"\"\"\\\\b\bf\fn\nr\rt\t"[excludeIdenticals ? 4 : 0];
|
||||
}
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
22
src/ArduinoJson/Data/JsonBufferAllocated.hpp
Normal file
22
src/ArduinoJson/Data/JsonBufferAllocated.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
class JsonBufferAllocated {
|
||||
public:
|
||||
void *operator new(size_t n, JsonBuffer *jsonBuffer) throw() {
|
||||
if (!jsonBuffer) return NULL;
|
||||
return jsonBuffer->alloc(n);
|
||||
}
|
||||
|
||||
void operator delete(void *, JsonBuffer *)throw();
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,16 +1,18 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
#if ARDUINOJSON_USE_DOUBLE
|
||||
typedef double JsonFloat;
|
||||
#else
|
||||
typedef float JsonFloat;
|
||||
#endif
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
|
@ -1,20 +1,23 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
|
||||
#include <stdint.h> // int64_t
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
typedef int64_t JsonInteger;
|
||||
typedef uint64_t JsonUInt;
|
||||
typedef long long JsonInteger;
|
||||
typedef unsigned long long JsonUInt;
|
||||
#elif ARDUINOJSON_USE_INT64
|
||||
typedef __int64 JsonInteger;
|
||||
typedef unsigned _int64 JsonUInt;
|
||||
#else
|
||||
typedef long JsonInteger;
|
||||
typedef unsigned long JsonUInt;
|
||||
#endif
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
|
@ -1,17 +1,11 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class JsonArray;
|
||||
class JsonArrayConst;
|
||||
class JsonObject;
|
||||
class JsonObjectConst;
|
||||
class JsonVariant;
|
||||
class JsonVariantConst;
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A metafunction that returns the type of the value returned by
|
||||
// JsonVariant::as<T>()
|
||||
@ -25,25 +19,24 @@ struct JsonVariantAs<char*> {
|
||||
typedef const char* type;
|
||||
};
|
||||
|
||||
// A metafunction that returns the type of the value returned by
|
||||
// JsonVariant::as<T>()
|
||||
template <typename T>
|
||||
struct JsonVariantConstAs {
|
||||
typedef typename JsonVariantAs<T>::type type;
|
||||
template <>
|
||||
struct JsonVariantAs<JsonArray> {
|
||||
typedef JsonArray& type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JsonVariantConstAs<JsonVariant> {
|
||||
typedef JsonVariantConst type;
|
||||
struct JsonVariantAs<const JsonArray> {
|
||||
typedef const JsonArray& type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JsonVariantConstAs<JsonObject> {
|
||||
typedef JsonObjectConst type;
|
||||
struct JsonVariantAs<JsonObject> {
|
||||
typedef JsonObject& type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct JsonVariantConstAs<JsonArray> {
|
||||
typedef JsonArrayConst type;
|
||||
struct JsonVariantAs<const JsonObject> {
|
||||
typedef const JsonObject& type;
|
||||
};
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
||||
|
27
src/ArduinoJson/Data/JsonVariantContent.hpp
Normal file
27
src/ArduinoJson/Data/JsonVariantContent.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonFloat.hpp"
|
||||
#include "JsonInteger.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
namespace Internals {
|
||||
// A union that defines the actual content of a JsonVariant.
|
||||
// The enum JsonVariantType determines which member is in use.
|
||||
union JsonVariantContent {
|
||||
JsonFloat asFloat; // used for double and float
|
||||
JsonUInt asInteger; // used for bool, char, short, int and longs
|
||||
const char* asString; // asString can be null
|
||||
JsonArray* asArray; // asArray cannot be null
|
||||
JsonObject* asObject; // asObject cannot be null
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,79 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // ptrdiff_t, size_t
|
||||
|
||||
#include "JsonFloat.hpp"
|
||||
#include "JsonInteger.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
enum JsonVariantType {
|
||||
JSON_NULL,
|
||||
JSON_LINKED_RAW,
|
||||
JSON_OWNED_RAW,
|
||||
JSON_LINKED_STRING,
|
||||
JSON_OWNED_STRING,
|
||||
JSON_BOOLEAN,
|
||||
JSON_POSITIVE_INTEGER,
|
||||
JSON_NEGATIVE_INTEGER,
|
||||
JSON_ARRAY,
|
||||
JSON_OBJECT,
|
||||
JSON_FLOAT
|
||||
};
|
||||
|
||||
struct JsonObjectData {
|
||||
struct Slot *head;
|
||||
struct Slot *tail;
|
||||
};
|
||||
|
||||
struct JsonArrayData {
|
||||
struct Slot *head;
|
||||
struct Slot *tail;
|
||||
};
|
||||
|
||||
struct RawData {
|
||||
const char *data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
// A union that defines the actual content of a JsonVariantData.
|
||||
// The enum JsonVariantType determines which member is in use.
|
||||
union JsonVariantContent {
|
||||
JsonFloat asFloat;
|
||||
JsonUInt asInteger;
|
||||
JsonArrayData asArray;
|
||||
JsonObjectData asObject;
|
||||
const char *asString;
|
||||
struct {
|
||||
const char *data;
|
||||
size_t size;
|
||||
} asRaw;
|
||||
};
|
||||
|
||||
// this struct must be a POD type to prevent error calling offsetof on clang
|
||||
struct JsonVariantData {
|
||||
bool keyIsStatic : 1;
|
||||
JsonVariantType type : 7;
|
||||
JsonVariantContent content;
|
||||
};
|
||||
|
||||
inline JsonVariantData *getVariantData(JsonArrayData *arr) {
|
||||
const ptrdiff_t offset = offsetof(JsonVariantData, content) -
|
||||
offsetof(JsonVariantContent, asArray);
|
||||
if (!arr) return 0;
|
||||
return reinterpret_cast<JsonVariantData *>(reinterpret_cast<char *>(arr) -
|
||||
offset);
|
||||
}
|
||||
|
||||
inline JsonVariantData *getVariantData(JsonObjectData *obj) {
|
||||
const ptrdiff_t offset = offsetof(JsonVariantData, content) -
|
||||
offsetof(JsonVariantContent, asObject);
|
||||
if (!obj) return 0;
|
||||
return reinterpret_cast<JsonVariantData *>(reinterpret_cast<char *>(obj) -
|
||||
offset);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
23
src/ArduinoJson/Data/JsonVariantDefault.hpp
Normal file
23
src/ArduinoJson/Data/JsonVariantDefault.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename T>
|
||||
struct JsonVariantDefault {
|
||||
static T get() {
|
||||
return T();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct JsonVariantDefault<const T> : JsonVariantDefault<T> {};
|
||||
|
||||
template <typename T>
|
||||
struct JsonVariantDefault<T&> : JsonVariantDefault<T> {};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,30 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
class JsonVariant;
|
||||
|
||||
// A metafunction that returns the type of the value returned by
|
||||
// JsonVariant::to<T>()
|
||||
template <typename T>
|
||||
struct JsonVariantTo {};
|
||||
|
||||
template <>
|
||||
struct JsonVariantTo<JsonArray> {
|
||||
typedef JsonArray type;
|
||||
};
|
||||
template <>
|
||||
struct JsonVariantTo<JsonObject> {
|
||||
typedef JsonObject type;
|
||||
};
|
||||
template <>
|
||||
struct JsonVariantTo<JsonVariant> {
|
||||
typedef JsonVariant type;
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
27
src/ArduinoJson/Data/JsonVariantType.hpp
Normal file
27
src/ArduinoJson/Data/JsonVariantType.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
|
||||
namespace Internals {
|
||||
|
||||
// Enumerated type to know the current type of a JsonVariant.
|
||||
// The value determines which member of JsonVariantContent is used.
|
||||
enum JsonVariantType {
|
||||
JSON_UNDEFINED, // JsonVariant has not been initialized
|
||||
JSON_UNPARSED, // JsonVariant contains an unparsed string
|
||||
JSON_STRING, // JsonVariant stores a const char*
|
||||
JSON_BOOLEAN, // JsonVariant stores a bool
|
||||
JSON_POSITIVE_INTEGER, // JsonVariant stores an JsonUInt
|
||||
JSON_NEGATIVE_INTEGER, // JsonVariant stores an JsonUInt that must be negated
|
||||
JSON_ARRAY, // JsonVariant stores a pointer to a JsonArray
|
||||
JSON_OBJECT, // JsonVariant stores a pointer to a JsonObject
|
||||
JSON_FLOAT // JsonVariant stores a JsonFloat
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
94
src/ArduinoJson/Data/List.hpp
Normal file
94
src/ArduinoJson/Data/List.hpp
Normal file
@ -0,0 +1,94 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "ListConstIterator.hpp"
|
||||
#include "ListIterator.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A singly linked list of T.
|
||||
// The linked list is composed of ListNode<T>.
|
||||
// It is derived by JsonArray and JsonObject
|
||||
template <typename T>
|
||||
class List {
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef ListNode<T> node_type;
|
||||
typedef ListIterator<T> iterator;
|
||||
typedef ListConstIterator<T> const_iterator;
|
||||
|
||||
// Creates an empty List<T> attached to a JsonBuffer.
|
||||
// The JsonBuffer allows to allocate new nodes.
|
||||
// When buffer is NULL, the List is not able to grow and success() returns
|
||||
// false. This is used to identify bad memory allocations and parsing
|
||||
// failures.
|
||||
explicit List(JsonBuffer *buffer) : _buffer(buffer), _firstNode(NULL) {}
|
||||
|
||||
// Returns true if the object is valid
|
||||
// Would return false in the following situation:
|
||||
// - the memory allocation failed (StaticJsonBuffer was too small)
|
||||
// - the JSON parsing failed
|
||||
bool success() const {
|
||||
return _buffer != NULL;
|
||||
}
|
||||
|
||||
// Returns the numbers of elements in the list.
|
||||
// For a JsonObject, it would return the number of key-value pairs
|
||||
size_t size() const {
|
||||
size_t nodeCount = 0;
|
||||
for (node_type *node = _firstNode; node; node = node->next) nodeCount++;
|
||||
return nodeCount;
|
||||
}
|
||||
|
||||
iterator add() {
|
||||
node_type *newNode = new (_buffer) node_type();
|
||||
|
||||
if (_firstNode) {
|
||||
node_type *lastNode = _firstNode;
|
||||
while (lastNode->next) lastNode = lastNode->next;
|
||||
lastNode->next = newNode;
|
||||
} else {
|
||||
_firstNode = newNode;
|
||||
}
|
||||
|
||||
return iterator(newNode);
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
return iterator(_firstNode);
|
||||
}
|
||||
iterator end() {
|
||||
return iterator(NULL);
|
||||
}
|
||||
|
||||
const_iterator begin() const {
|
||||
return const_iterator(_firstNode);
|
||||
}
|
||||
const_iterator end() const {
|
||||
return const_iterator(NULL);
|
||||
}
|
||||
|
||||
void remove(iterator it) {
|
||||
node_type *nodeToRemove = it._node;
|
||||
if (!nodeToRemove) return;
|
||||
if (nodeToRemove == _firstNode) {
|
||||
_firstNode = nodeToRemove->next;
|
||||
} else {
|
||||
for (node_type *node = _firstNode; node; node = node->next)
|
||||
if (node->next == nodeToRemove) node->next = nodeToRemove->next;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
JsonBuffer *_buffer;
|
||||
|
||||
private:
|
||||
node_type *_firstNode;
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
50
src/ArduinoJson/Data/ListConstIterator.hpp
Normal file
50
src/ArduinoJson/Data/ListConstIterator.hpp
Normal file
@ -0,0 +1,50 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ListNode.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A read-only forward itertor for List<T>
|
||||
template <typename T>
|
||||
class ListConstIterator {
|
||||
public:
|
||||
explicit ListConstIterator(const ListNode<T> *node = NULL) : _node(node) {}
|
||||
|
||||
const T &operator*() const {
|
||||
return _node->content;
|
||||
}
|
||||
const T *operator->() {
|
||||
return &_node->content;
|
||||
}
|
||||
|
||||
bool operator==(const ListConstIterator<T> &other) const {
|
||||
return _node == other._node;
|
||||
}
|
||||
|
||||
bool operator!=(const ListConstIterator<T> &other) const {
|
||||
return _node != other._node;
|
||||
}
|
||||
|
||||
ListConstIterator<T> &operator++() {
|
||||
if (_node) _node = _node->next;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ListConstIterator<T> &operator+=(size_t distance) {
|
||||
while (_node && distance) {
|
||||
_node = _node->next;
|
||||
--distance;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
const ListNode<T> *_node;
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
60
src/ArduinoJson/Data/ListIterator.hpp
Normal file
60
src/ArduinoJson/Data/ListIterator.hpp
Normal file
@ -0,0 +1,60 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ListConstIterator.hpp"
|
||||
#include "ListNode.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename T>
|
||||
class List;
|
||||
|
||||
// A read-write forward iterator for List<T>
|
||||
template <typename T>
|
||||
class ListIterator {
|
||||
friend class List<T>;
|
||||
|
||||
public:
|
||||
explicit ListIterator(ListNode<T> *node = NULL) : _node(node) {}
|
||||
|
||||
T &operator*() const {
|
||||
return _node->content;
|
||||
}
|
||||
T *operator->() {
|
||||
return &_node->content;
|
||||
}
|
||||
|
||||
bool operator==(const ListIterator<T> &other) const {
|
||||
return _node == other._node;
|
||||
}
|
||||
|
||||
bool operator!=(const ListIterator<T> &other) const {
|
||||
return _node != other._node;
|
||||
}
|
||||
|
||||
ListIterator<T> &operator++() {
|
||||
if (_node) _node = _node->next;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ListIterator<T> &operator+=(size_t distance) {
|
||||
while (_node && distance) {
|
||||
_node = _node->next;
|
||||
--distance;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator ListConstIterator<T>() const {
|
||||
return ListConstIterator<T>(_node);
|
||||
}
|
||||
|
||||
private:
|
||||
ListNode<T> *_node;
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
24
src/ArduinoJson/Data/ListNode.hpp
Normal file
24
src/ArduinoJson/Data/ListNode.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h> // for NULL
|
||||
|
||||
#include "JsonBufferAllocated.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A node for a singly-linked list.
|
||||
// Used by List<T> and its iterators.
|
||||
template <typename T>
|
||||
struct ListNode : public Internals::JsonBufferAllocated {
|
||||
ListNode() throw() : next(NULL) {}
|
||||
|
||||
ListNode<T> *next;
|
||||
T content;
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
23
src/ArduinoJson/Data/NonCopyable.hpp
Normal file
23
src/ArduinoJson/Data/NonCopyable.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A type that cannot be copied
|
||||
class NonCopyable {
|
||||
protected:
|
||||
NonCopyable() {}
|
||||
|
||||
private:
|
||||
// copy constructor is private
|
||||
NonCopyable(const NonCopyable&);
|
||||
|
||||
// copy operator is private
|
||||
NonCopyable& operator=(const NonCopyable&);
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,123 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "JsonVariantData.hpp"
|
||||
#include "SlotFunctions.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TKey>
|
||||
inline Slot* objectFindSlot(const JsonObjectData* obj, TKey key) {
|
||||
if (!obj) return 0;
|
||||
Slot* slot = obj->head;
|
||||
while (slot) {
|
||||
if (key.equals(slot->key)) break;
|
||||
slot = slot->next;
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
inline bool objectContainsKey(const JsonObjectData* obj, const TKey& key) {
|
||||
return objectFindSlot(obj, key) != 0;
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
inline JsonVariantData* objectAdd(JsonObjectData* obj, TKey key,
|
||||
MemoryPool* pool) {
|
||||
Slot* slot = new (pool) Slot();
|
||||
if (!slot) return 0;
|
||||
|
||||
slot->next = 0;
|
||||
|
||||
if (obj->tail) {
|
||||
slot->prev = obj->tail;
|
||||
obj->tail->next = slot;
|
||||
obj->tail = slot;
|
||||
} else {
|
||||
slot->prev = 0;
|
||||
obj->head = slot;
|
||||
obj->tail = slot;
|
||||
}
|
||||
|
||||
if (!slotSetKey(slot, key, pool)) return 0;
|
||||
return &slot->value;
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
inline JsonVariantData* objectSet(JsonObjectData* obj, TKey key,
|
||||
MemoryPool* pool) {
|
||||
if (!obj) return 0;
|
||||
|
||||
// ignore null key
|
||||
if (key.isNull()) return 0;
|
||||
|
||||
// search a matching key
|
||||
Slot* slot = objectFindSlot(obj, key);
|
||||
if (slot) return &slot->value;
|
||||
|
||||
return objectAdd(obj, key, pool);
|
||||
}
|
||||
|
||||
template <typename TKey>
|
||||
inline JsonVariantData* objectGet(const JsonObjectData* obj, TKey key) {
|
||||
Slot* slot = objectFindSlot(obj, key);
|
||||
return slot ? &slot->value : 0;
|
||||
}
|
||||
|
||||
inline void objectClear(JsonObjectData* obj) {
|
||||
if (!obj) return;
|
||||
obj->head = 0;
|
||||
obj->tail = 0;
|
||||
}
|
||||
|
||||
inline void objectRemove(JsonObjectData* obj, Slot* slot) {
|
||||
if (!obj) return;
|
||||
if (!slot) return;
|
||||
if (slot->prev)
|
||||
slot->prev->next = slot->next;
|
||||
else
|
||||
obj->head = slot->next;
|
||||
if (slot->next)
|
||||
slot->next->prev = slot->prev;
|
||||
else
|
||||
obj->tail = slot->prev;
|
||||
}
|
||||
|
||||
inline size_t objectSize(const JsonObjectData* obj) {
|
||||
if (!obj) return 0;
|
||||
return slotSize(obj->head);
|
||||
}
|
||||
|
||||
// bool variantCopy(JsonVariantData*, const JsonVariantData*, MemoryPool*);
|
||||
|
||||
inline bool objectCopy(JsonObjectData* dst, const JsonObjectData* src,
|
||||
MemoryPool* pool) {
|
||||
if (!dst || !src) return false;
|
||||
objectClear(dst);
|
||||
for (Slot* s = src->head; s; s = s->next) {
|
||||
JsonVariantData* var;
|
||||
if (s->value.keyIsStatic)
|
||||
var = objectAdd(dst, ZeroTerminatedRamStringConst(s->key), pool);
|
||||
else
|
||||
var = objectAdd(dst, ZeroTerminatedRamString(s->key), pool);
|
||||
if (!variantCopy(var, &s->value, pool)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool objectEquals(const JsonObjectData* o1, const JsonObjectData* o2) {
|
||||
if (o1 == o2) return true;
|
||||
if (!o1 || !o2) return false;
|
||||
|
||||
for (Slot* s = o1->head; s; s = s->next) {
|
||||
JsonVariantData* v1 = &s->value;
|
||||
JsonVariantData* v2 = objectGet(o2, makeString(s->key));
|
||||
if (!variantEquals(v1, v2)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
24
src/ArduinoJson/Data/ReferenceType.hpp
Normal file
24
src/ArduinoJson/Data/ReferenceType.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// A type that is meant to be used by reference only (JsonArray and JsonObject)
|
||||
class ReferenceType {
|
||||
public:
|
||||
bool operator==(const ReferenceType& other) const {
|
||||
// two JsonArray are equal if they are the same instance
|
||||
// (we don't compare the content)
|
||||
return this == &other;
|
||||
}
|
||||
|
||||
bool operator!=(const ReferenceType& other) const {
|
||||
return this != &other;
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,19 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Memory/AllocableInMemoryPool.hpp"
|
||||
#include "JsonVariantData.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
struct Slot : AllocableInMemoryPool {
|
||||
JsonVariantData value;
|
||||
struct Slot* next;
|
||||
struct Slot* prev;
|
||||
const char* key;
|
||||
};
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,59 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Strings/StringTypes.hpp"
|
||||
#include "JsonVariantData.hpp"
|
||||
#include "Slot.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TKey>
|
||||
inline bool slotSetKey(Slot* slot, TKey key, MemoryPool* pool) {
|
||||
const char* dup = key.save(pool);
|
||||
if (!dup) return false;
|
||||
slot->key = dup;
|
||||
slot->value.keyIsStatic = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool slotSetKey(Slot* slot, ZeroTerminatedRamStringConst key,
|
||||
MemoryPool* pool) {
|
||||
slot->key = key.save(pool);
|
||||
slot->value.keyIsStatic = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool slotSetKey(Slot* slot, StringInMemoryPool key, MemoryPool* pool) {
|
||||
slot->key = key.save(pool);
|
||||
slot->value.keyIsStatic = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline const Slot* slotAdvance(const Slot* slot, size_t distance) {
|
||||
while (distance && slot) {
|
||||
slot = slot->next;
|
||||
distance--;
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
|
||||
inline Slot* slotAdvance(Slot* slot, size_t distance) {
|
||||
while (distance && slot) {
|
||||
slot = slot->next;
|
||||
distance--;
|
||||
}
|
||||
return slot;
|
||||
}
|
||||
|
||||
inline size_t slotSize(const Slot* slot) {
|
||||
size_t n = 0;
|
||||
while (slot) {
|
||||
n++;
|
||||
slot = slot->next;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
52
src/ArduinoJson/Data/ValueSaver.hpp
Normal file
52
src/ArduinoJson/Data/ValueSaver.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../StringTraits/StringTraits.hpp"
|
||||
#include "../TypeTraits/EnableIf.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename Source, typename Enable = void>
|
||||
struct ValueSaver {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer*, Destination& destination, Source source) {
|
||||
destination = source;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Source>
|
||||
struct ValueSaver<
|
||||
Source, typename EnableIf<StringTraits<Source>::should_duplicate>::type> {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer* buffer, Destination& dest, Source source) {
|
||||
if (!StringTraits<Source>::is_null(source)) {
|
||||
typename StringTraits<Source>::duplicate_t dup =
|
||||
StringTraits<Source>::duplicate(source, buffer);
|
||||
if (!dup) return false;
|
||||
dest = dup;
|
||||
} else {
|
||||
dest = reinterpret_cast<const char*>(0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// const char*, const signed char*, const unsigned char*
|
||||
template <typename Char>
|
||||
struct ValueSaver<
|
||||
Char*, typename EnableIf<!StringTraits<Char*>::should_duplicate>::type> {
|
||||
template <typename Destination>
|
||||
static bool save(JsonBuffer*, Destination& dest, Char* source) {
|
||||
dest = reinterpret_cast<const char*>(source);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,48 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Serialization/DynamicStringWriter.hpp"
|
||||
#include "VariantFunctions.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class JsonVariantConst;
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_integral<T>::value, T>::type variantAs(
|
||||
const JsonVariantData* _data) {
|
||||
return variantAsIntegral<T>(_data);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_same<T, bool>::value, T>::type variantAs(
|
||||
const JsonVariantData* _data) {
|
||||
return variantAsBoolean(_data);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_floating_point<T>::value, T>::type variantAs(
|
||||
const JsonVariantData* _data) {
|
||||
return variantAsFloat<T>(_data);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_same<T, const char*>::value ||
|
||||
is_same<T, char*>::value,
|
||||
const char*>::type
|
||||
variantAs(const JsonVariantData* _data) {
|
||||
return variantAsString(_data);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_same<JsonVariantConst, T>::value, T>::type
|
||||
variantAs(const JsonVariantData* _data);
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs(
|
||||
const JsonVariantData* _data);
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,29 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../Serialization/DynamicStringWriter.hpp"
|
||||
#include "VariantFunctions.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<is_same<JsonVariantConst, T>::value, T>::type
|
||||
variantAs(const JsonVariantData* _data) {
|
||||
return JsonVariantConst(_data);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs(
|
||||
const JsonVariantData* _data) {
|
||||
const char* cstr = variantAsString(_data);
|
||||
if (cstr) return T(cstr);
|
||||
T s;
|
||||
serializeJson(JsonVariantConst(_data), s);
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,287 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Numbers/parseFloat.hpp"
|
||||
#include "../Numbers/parseInteger.hpp"
|
||||
#include "../SerializedValue.hpp"
|
||||
#include "ArrayFunctions.hpp"
|
||||
#include "JsonVariantData.hpp"
|
||||
#include "ObjectFunctions.hpp"
|
||||
#include "Slot.hpp"
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename T>
|
||||
inline T variantAsIntegral(const JsonVariantData* var) {
|
||||
if (!var) return 0;
|
||||
switch (var->type) {
|
||||
case JSON_POSITIVE_INTEGER:
|
||||
case JSON_BOOLEAN:
|
||||
return T(var->content.asInteger);
|
||||
case JSON_NEGATIVE_INTEGER:
|
||||
return T(~var->content.asInteger + 1);
|
||||
case JSON_LINKED_STRING:
|
||||
case JSON_OWNED_STRING:
|
||||
return parseInteger<T>(var->content.asString);
|
||||
case JSON_FLOAT:
|
||||
return T(var->content.asFloat);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool variantAsBoolean(const JsonVariantData* var) {
|
||||
return variantAsIntegral<int>(var) != 0;
|
||||
}
|
||||
|
||||
// T = float/double
|
||||
template <typename T>
|
||||
inline T variantAsFloat(const JsonVariantData* var) {
|
||||
if (!var) return 0;
|
||||
switch (var->type) {
|
||||
case JSON_POSITIVE_INTEGER:
|
||||
case JSON_BOOLEAN:
|
||||
return static_cast<T>(var->content.asInteger);
|
||||
case JSON_NEGATIVE_INTEGER:
|
||||
return -static_cast<T>(var->content.asInteger);
|
||||
case JSON_LINKED_STRING:
|
||||
case JSON_OWNED_STRING:
|
||||
return parseFloat<T>(var->content.asString);
|
||||
case JSON_FLOAT:
|
||||
return static_cast<T>(var->content.asFloat);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline const char* variantAsString(const JsonVariantData* var) {
|
||||
if (!var) return 0;
|
||||
if (var &&
|
||||
(var->type == JSON_LINKED_STRING || var->type == JSON_OWNED_STRING))
|
||||
return var->content.asString;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline JsonArrayData* variantAsArray(JsonVariantData* var) {
|
||||
if (var && var->type == JSON_ARRAY)
|
||||
return &var->content.asArray;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline const JsonArrayData* variantAsArray(const JsonVariantData* var) {
|
||||
if (var && var->type == JSON_ARRAY)
|
||||
return &var->content.asArray;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline JsonObjectData* variantAsObject(JsonVariantData* var) {
|
||||
if (var && var->type == JSON_OBJECT)
|
||||
return &var->content.asObject;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline const JsonObjectData* variantAsObject(const JsonVariantData* var) {
|
||||
if (var && var->type == JSON_OBJECT)
|
||||
return &var->content.asObject;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline bool variantSetBoolean(JsonVariantData* var, bool value) {
|
||||
if (!var) return false;
|
||||
var->type = JSON_BOOLEAN;
|
||||
var->content.asInteger = static_cast<JsonUInt>(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool variantSetFloat(JsonVariantData* var, JsonFloat value) {
|
||||
if (!var) return false;
|
||||
var->type = JSON_FLOAT;
|
||||
var->content.asFloat = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool variantSetSignedInteger(JsonVariantData* var, T value) {
|
||||
if (!var) return false;
|
||||
if (value >= 0) {
|
||||
var->type = JSON_POSITIVE_INTEGER;
|
||||
var->content.asInteger = static_cast<JsonUInt>(value);
|
||||
} else {
|
||||
var->type = JSON_NEGATIVE_INTEGER;
|
||||
var->content.asInteger = ~static_cast<JsonUInt>(value) + 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool variantSetSignedInteger(JsonVariantData* var, JsonUInt value) {
|
||||
if (!var) return false;
|
||||
var->type = JSON_POSITIVE_INTEGER;
|
||||
var->content.asInteger = static_cast<JsonUInt>(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool variantSetLinkedRaw(JsonVariantData* var,
|
||||
SerializedValue<const char*> value) {
|
||||
if (!var) return false;
|
||||
var->type = JSON_LINKED_RAW;
|
||||
var->content.asRaw.data = value.data();
|
||||
var->content.asRaw.size = value.size();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool variantSetOwnedRaw(JsonVariantData* var, SerializedValue<T> value,
|
||||
MemoryPool* pool) {
|
||||
if (!var) return false;
|
||||
const char* dup = makeString(value.data(), value.size()).save(pool);
|
||||
if (dup) {
|
||||
var->type = JSON_OWNED_RAW;
|
||||
var->content.asRaw.data = dup;
|
||||
var->content.asRaw.size = value.size();
|
||||
return true;
|
||||
} else {
|
||||
var->type = JSON_NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool variantSetString(JsonVariantData* var, T value, MemoryPool* pool) {
|
||||
if (!var) return false;
|
||||
const char* dup = value.save(pool);
|
||||
if (dup) {
|
||||
var->type = JSON_OWNED_STRING;
|
||||
var->content.asString = dup;
|
||||
return true;
|
||||
} else {
|
||||
var->type = JSON_NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool variantSetString(JsonVariantData* var, const char* value) {
|
||||
if (!var) return false;
|
||||
var->type = JSON_LINKED_STRING;
|
||||
var->content.asString = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool variantSetString(JsonVariantData* var, const char* value,
|
||||
MemoryPool* pool) {
|
||||
return variantSetString(var, makeString(const_cast<char*>(value)), pool);
|
||||
}
|
||||
|
||||
inline void variantSetNull(JsonVariantData* var) {
|
||||
if (var) var->type = JSON_NULL;
|
||||
}
|
||||
|
||||
inline JsonArrayData* variantToArray(JsonVariantData* var) {
|
||||
if (!var) return 0;
|
||||
var->type = JSON_ARRAY;
|
||||
var->content.asArray.head = 0;
|
||||
var->content.asArray.tail = 0;
|
||||
return &var->content.asArray;
|
||||
}
|
||||
|
||||
inline JsonObjectData* variantToObject(JsonVariantData* var) {
|
||||
if (!var) return 0;
|
||||
var->type = JSON_OBJECT;
|
||||
var->content.asObject.head = 0;
|
||||
var->content.asObject.tail = 0;
|
||||
return &var->content.asObject;
|
||||
}
|
||||
|
||||
inline bool variantCopy(JsonVariantData* dst, const JsonVariantData* src,
|
||||
MemoryPool* pool) {
|
||||
if (!dst) return false;
|
||||
if (!src) {
|
||||
dst->type = JSON_NULL;
|
||||
return true;
|
||||
}
|
||||
switch (src->type) {
|
||||
case JSON_ARRAY:
|
||||
return arrayCopy(variantToArray(dst), &src->content.asArray, pool);
|
||||
case JSON_OBJECT:
|
||||
return objectCopy(variantToObject(dst), &src->content.asObject, pool);
|
||||
case JSON_OWNED_STRING:
|
||||
return variantSetString(dst, src->content.asString, pool);
|
||||
case JSON_OWNED_RAW:
|
||||
return variantSetOwnedRaw(
|
||||
dst,
|
||||
serialized(const_cast<char*>(src->content.asRaw.data),
|
||||
src->content.asRaw.size),
|
||||
pool);
|
||||
default:
|
||||
*dst = *src;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool variantIsInteger(const JsonVariantData* var) {
|
||||
return var && (var->type == JSON_POSITIVE_INTEGER ||
|
||||
var->type == JSON_NEGATIVE_INTEGER);
|
||||
}
|
||||
|
||||
inline bool variantIsFloat(const JsonVariantData* var) {
|
||||
return var &&
|
||||
(var->type == JSON_FLOAT || var->type == JSON_POSITIVE_INTEGER ||
|
||||
var->type == JSON_NEGATIVE_INTEGER);
|
||||
}
|
||||
|
||||
inline bool variantIsString(const JsonVariantData* var) {
|
||||
return var &&
|
||||
(var->type == JSON_LINKED_STRING || var->type == JSON_OWNED_STRING);
|
||||
}
|
||||
|
||||
inline bool variantIsArray(const JsonVariantData* var) {
|
||||
return var && var->type == JSON_ARRAY;
|
||||
}
|
||||
|
||||
inline bool variantIsObject(const JsonVariantData* var) {
|
||||
return var && var->type == JSON_OBJECT;
|
||||
}
|
||||
|
||||
inline bool variantIsNull(const JsonVariantData* var) {
|
||||
return var == 0 || var->type == JSON_NULL;
|
||||
}
|
||||
|
||||
inline bool variantEquals(const JsonVariantData* a, const JsonVariantData* b) {
|
||||
if (a == b) return true;
|
||||
if (!a || !b) return false;
|
||||
if (a->type != b->type) return false;
|
||||
|
||||
switch (a->type) {
|
||||
case JSON_LINKED_RAW:
|
||||
case JSON_OWNED_RAW:
|
||||
case JSON_LINKED_STRING:
|
||||
case JSON_OWNED_STRING:
|
||||
return !strcmp(a->content.asString, b->content.asString);
|
||||
|
||||
case JSON_BOOLEAN:
|
||||
case JSON_POSITIVE_INTEGER:
|
||||
case JSON_NEGATIVE_INTEGER:
|
||||
return a->content.asInteger == b->content.asInteger;
|
||||
|
||||
case JSON_ARRAY:
|
||||
return arrayEquals(&a->content.asArray, &b->content.asArray);
|
||||
|
||||
case JSON_OBJECT:
|
||||
return objectEquals(&a->content.asObject, &b->content.asObject);
|
||||
|
||||
case JSON_FLOAT:
|
||||
return a->content.asFloat == b->content.asFloat;
|
||||
|
||||
case JSON_NULL:
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,39 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
|
||||
|
||||
#include <Stream.h>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
struct ArduinoStreamReader {
|
||||
Stream& _stream;
|
||||
char _current;
|
||||
bool _ended;
|
||||
|
||||
public:
|
||||
explicit ArduinoStreamReader(Stream& stream)
|
||||
: _stream(stream), _current(0), _ended(false) {}
|
||||
|
||||
char read() {
|
||||
// don't use _stream.read() as it ignores the timeout
|
||||
char c = 0;
|
||||
_ended = _stream.readBytes(&c, 1) == 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
return _ended;
|
||||
}
|
||||
};
|
||||
|
||||
inline ArduinoStreamReader makeReader(Stream& input) {
|
||||
return ArduinoStreamReader(input);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
#endif
|
@ -1,62 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TChar>
|
||||
class UnsafeCharPointerReader {
|
||||
const TChar* _ptr;
|
||||
|
||||
public:
|
||||
explicit UnsafeCharPointerReader(const TChar* ptr)
|
||||
: _ptr(ptr ? ptr : reinterpret_cast<const TChar*>("")) {}
|
||||
|
||||
char read() {
|
||||
return static_cast<char>(*_ptr++);
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
// we cannot know
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TChar>
|
||||
class SafeCharPointerReader {
|
||||
const TChar* _ptr;
|
||||
const TChar* _end;
|
||||
|
||||
public:
|
||||
explicit SafeCharPointerReader(const TChar* ptr, size_t len)
|
||||
: _ptr(ptr ? ptr : reinterpret_cast<const TChar*>("")),
|
||||
_end(_ptr + len) {}
|
||||
|
||||
char read() {
|
||||
return static_cast<char>(*_ptr++);
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
return _ptr == _end;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TChar>
|
||||
inline UnsafeCharPointerReader<TChar> makeReader(TChar* input) {
|
||||
return UnsafeCharPointerReader<TChar>(input);
|
||||
}
|
||||
|
||||
template <typename TChar>
|
||||
inline SafeCharPointerReader<TChar> makeReader(TChar* input, size_t n) {
|
||||
return SafeCharPointerReader<TChar>(input, n);
|
||||
}
|
||||
|
||||
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
|
||||
inline SafeCharPointerReader<char> makeReader(const String& input) {
|
||||
return SafeCharPointerReader<char>(input.c_str(), input.length());
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
61
src/ArduinoJson/Deserialization/Comments.hpp
Normal file
61
src/ArduinoJson/Deserialization/Comments.hpp
Normal file
@ -0,0 +1,61 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
template <typename TInput>
|
||||
void skipSpacesAndComments(TInput& input) {
|
||||
for (;;) {
|
||||
switch (input.current()) {
|
||||
// spaces
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
input.move();
|
||||
continue;
|
||||
|
||||
// comments
|
||||
case '/':
|
||||
switch (input.next()) {
|
||||
// C-style block comment
|
||||
case '*':
|
||||
input.move(); // skip '/'
|
||||
// no need to skip '*'
|
||||
for (;;) {
|
||||
input.move();
|
||||
if (input.current() == '\0') return;
|
||||
if (input.current() == '*' && input.next() == '/') {
|
||||
input.move(); // skip '*'
|
||||
input.move(); // skip '/'
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// C++-style line comment
|
||||
case '/':
|
||||
// not need to skip "//"
|
||||
for (;;) {
|
||||
input.move();
|
||||
if (input.current() == '\0') return;
|
||||
if (input.current() == '\n') break;
|
||||
}
|
||||
break;
|
||||
|
||||
// not a comment, just a '/'
|
||||
default:
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
@ -1,83 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
#include <ostream>
|
||||
#endif
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
class DeserializationError {
|
||||
public:
|
||||
enum Code {
|
||||
Ok,
|
||||
IncompleteInput,
|
||||
InvalidInput,
|
||||
NoMemory,
|
||||
NotSupported,
|
||||
TooDeep
|
||||
};
|
||||
|
||||
DeserializationError() {}
|
||||
DeserializationError(Code code) : _code(code) {}
|
||||
|
||||
friend bool operator==(const DeserializationError& err, Code code) {
|
||||
return err._code == code;
|
||||
}
|
||||
|
||||
friend bool operator==(Code code, const DeserializationError& err) {
|
||||
return err._code == code;
|
||||
}
|
||||
|
||||
friend bool operator!=(const DeserializationError& err, Code code) {
|
||||
return err._code != code;
|
||||
}
|
||||
|
||||
friend bool operator!=(Code code, const DeserializationError& err) {
|
||||
return err._code != code;
|
||||
}
|
||||
|
||||
operator bool() const {
|
||||
return _code != Ok;
|
||||
}
|
||||
|
||||
const char* c_str() const {
|
||||
switch (_code) {
|
||||
case Ok:
|
||||
return "Ok";
|
||||
case TooDeep:
|
||||
return "TooDeep";
|
||||
case NoMemory:
|
||||
return "NoMemory";
|
||||
case InvalidInput:
|
||||
return "InvalidInput";
|
||||
case IncompleteInput:
|
||||
return "IncompleteInput";
|
||||
case NotSupported:
|
||||
return "NotSupported";
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Code _code;
|
||||
};
|
||||
|
||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||
inline std::ostream& operator<<(std::ostream& s,
|
||||
const DeserializationError& e) {
|
||||
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
|
@ -1,54 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#if ARDUINOJSON_ENABLE_PROGMEM
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
class UnsafeFlashStringReader {
|
||||
const char* _ptr;
|
||||
|
||||
public:
|
||||
explicit UnsafeFlashStringReader(const __FlashStringHelper* ptr)
|
||||
: _ptr(reinterpret_cast<const char*>(ptr)) {}
|
||||
|
||||
char read() {
|
||||
return pgm_read_byte_near(_ptr++);
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
// this reader cannot detect the end
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class SafeFlashStringReader {
|
||||
const char* _ptr;
|
||||
const char* _end;
|
||||
|
||||
public:
|
||||
explicit SafeFlashStringReader(const __FlashStringHelper* ptr, size_t size)
|
||||
: _ptr(reinterpret_cast<const char*>(ptr)), _end(_ptr + size) {}
|
||||
|
||||
char read() {
|
||||
return pgm_read_byte_near(_ptr++);
|
||||
}
|
||||
|
||||
bool ended() const {
|
||||
return _ptr == _end;
|
||||
}
|
||||
};
|
||||
|
||||
inline UnsafeFlashStringReader makeReader(const __FlashStringHelper* input) {
|
||||
return UnsafeFlashStringReader(input);
|
||||
}
|
||||
|
||||
inline SafeFlashStringReader makeReader(const __FlashStringHelper* input,
|
||||
size_t size) {
|
||||
return SafeFlashStringReader(input, size);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
#endif
|
@ -1,32 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2018
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TIterator>
|
||||
class IteratorReader {
|
||||
TIterator _ptr, _end;
|
||||
|
||||
public:
|
||||
explicit IteratorReader(TIterator begin, TIterator end)
|
||||
: _ptr(begin), _end(end) {}
|
||||
|
||||
bool ended() const {
|
||||
return _ptr == _end;
|
||||
}
|
||||
|
||||
char read() {
|
||||
return char(*_ptr++);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TInput>
|
||||
inline IteratorReader<typename TInput::const_iterator> makeReader(
|
||||
const TInput& input) {
|
||||
return IteratorReader<typename TInput::const_iterator>(input.begin(),
|
||||
input.end());
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
102
src/ArduinoJson/Deserialization/JsonParser.hpp
Normal file
102
src/ArduinoJson/Deserialization/JsonParser.hpp
Normal file
@ -0,0 +1,102 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2019
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonBuffer.hpp"
|
||||
#include "../JsonVariant.hpp"
|
||||
#include "../TypeTraits/IsConst.hpp"
|
||||
#include "StringWriter.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
// Parse JSON string to create JsonArrays and JsonObjects
|
||||
// This internal class is not indended to be used directly.
|
||||
// Instead, use JsonBuffer.parseArray() or .parseObject()
|
||||
template <typename TReader, typename TWriter>
|
||||
class JsonParser {
|
||||
public:
|
||||
JsonParser(JsonBuffer *buffer, TReader reader, TWriter writer,
|
||||
uint8_t nestingLimit)
|
||||
: _buffer(buffer),
|
||||
_reader(reader),
|
||||
_writer(writer),
|
||||
_nestingLimit(nestingLimit) {}
|
||||
|
||||
JsonArray &parseArray();
|
||||
JsonObject &parseObject();
|
||||
|
||||
JsonVariant parseVariant() {
|
||||
JsonVariant result;
|
||||
parseAnythingTo(&result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
JsonParser &operator=(const JsonParser &); // non-copiable
|
||||
|
||||
static bool eat(TReader &, char charToSkip);
|
||||
FORCE_INLINE bool eat(char charToSkip) {
|
||||
return eat(_reader, charToSkip);
|
||||
}
|
||||
|
||||
const char *parseString();
|
||||
bool parseAnythingTo(JsonVariant *destination);
|
||||
|
||||
inline bool parseArrayTo(JsonVariant *destination);
|
||||
inline bool parseObjectTo(JsonVariant *destination);
|
||||
inline bool parseStringTo(JsonVariant *destination);
|
||||
|
||||
static inline bool isBetween(char c, char min, char max) {
|
||||
return min <= c && c <= max;
|
||||
}
|
||||
|
||||
static inline bool canBeInNonQuotedString(char c) {
|
||||
return isBetween(c, '0', '9') || isBetween(c, '_', 'z') ||
|
||||
isBetween(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
|
||||
}
|
||||
|
||||
static inline bool isQuote(char c) {
|
||||
return c == '\'' || c == '\"';
|
||||
}
|
||||
|
||||
JsonBuffer *_buffer;
|
||||
TReader _reader;
|
||||
TWriter _writer;
|
||||
uint8_t _nestingLimit;
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TString, typename Enable = void>
|
||||
struct JsonParserBuilder {
|
||||
typedef typename StringTraits<TString>::Reader InputReader;
|
||||
typedef JsonParser<InputReader, TJsonBuffer &> TParser;
|
||||
|
||||
static TParser makeParser(TJsonBuffer *buffer, TString &json,
|
||||
uint8_t nestingLimit) {
|
||||
return TParser(buffer, InputReader(json), *buffer, nestingLimit);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TChar>
|
||||
struct JsonParserBuilder<TJsonBuffer, TChar *,
|
||||
typename EnableIf<!IsConst<TChar>::value>::type> {
|
||||
typedef typename StringTraits<TChar *>::Reader TReader;
|
||||
typedef StringWriter<TChar> TWriter;
|
||||
typedef JsonParser<TReader, TWriter> TParser;
|
||||
|
||||
static TParser makeParser(TJsonBuffer *buffer, TChar *json,
|
||||
uint8_t nestingLimit) {
|
||||
return TParser(buffer, TReader(json), TWriter(json), nestingLimit);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TJsonBuffer, typename TString>
|
||||
inline typename JsonParserBuilder<TJsonBuffer, TString>::TParser makeParser(
|
||||
TJsonBuffer *buffer, TString &json, uint8_t nestingLimit) {
|
||||
return JsonParserBuilder<TJsonBuffer, TString>::makeParser(buffer, json,
|
||||
nestingLimit);
|
||||
}
|
||||
} // namespace Internals
|
||||
} // namespace ArduinoJson
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user