Compare commits

..

25 Commits

Author SHA1 Message Date
4fe2b1100e Set version to 6.0.1-beta 2018-06-11 12:24:33 +02:00
c3403ed72d Fixed conflicts with isnan() and isinf() macros (fixes #752) 2018-06-11 12:21:50 +02:00
393f352b70 Minor changes in the examples 2018-06-07 11:21:54 +02:00
e86eb0cfdf Set version to 6.0.0-beta 2018-06-07 10:50:10 +02:00
a9a730fd74 Added MessagePack fuzzing 2018-06-07 10:36:57 +02:00
4ff6809bc5 Merge branch 'master' into 6.x 2018-06-07 09:32:55 +02:00
f53fc3e06f Added MessagePack in README 2018-06-04 17:48:10 +02:00
0139354780 Merge branch 'master' into 6.x 2018-06-04 17:46:34 +02:00
fc2e3a4ab3 Added serializeMsgPack() and measureMsgPack() (closes #358) 2018-05-29 08:31:39 +02:00
58cb793c96 Reorganized polyfills 2018-05-17 13:46:23 +02:00
4592f23260 Merged MsgPackError and JsonError into DeserializationError.
Return NotSupported if the JSON input contains "\u".
2018-05-15 18:23:09 +02:00
ccb54136a2 Added support for non zero-terminated strings (fixes #704) 2018-05-14 17:12:59 +02:00
4c9c047ddf Made nestingLimit a member of the document 2018-04-18 21:42:30 +02:00
1feb92679d Added StaticJsonDocument and DynamicJsonDocument.
Removed StaticJsonArray and DynamicJsonArray.
Removed StaticJsonObject and DynamicJsonObject.
Removed StaticJsonVariant and DynamicJsonVariant.
2018-04-17 21:27:45 +02:00
a13b9e8bdc Added example MsgPackParser.ino (issue #358) 2018-04-10 17:55:51 +02:00
cb723840d9 Added deserializeMsgPack() (issue #358) 2018-04-10 17:43:27 +02:00
923d3e8a84 Removed friend relationship between JsonVariant and JsonSerializer 2018-03-23 09:20:50 +01:00
0d1623edef Clear the JsonObject or JsonArray in deserializeJson() 2018-03-18 14:50:52 +01:00
cf149940ed Moved JsonBuffer to Memory/ 2018-03-15 16:51:07 +01:00
ef55a6ba7c Removed all deprecated features 2018-03-15 16:50:39 +01:00
e3e4aa89ad Merge branch 'master' into 6.x
# Conflicts:
#	CHANGELOG.md
#	src/ArduinoJson/Deserialization/JsonParser.hpp
#	src/ArduinoJson/Deserialization/JsonParserImpl.hpp
#	test/JsonBuffer/nestingLimit.cpp
2018-03-14 14:46:53 +01:00
b2a8085651 Added JsonError 2018-03-09 16:58:01 +01:00
83d73c93f7 Replaced printTo() with serializeJson()
* Added `serializeJson()` and `serializeJsonPretty()`
* Added `measureJson()` and `measureJsonPretty()`
* Removed `printTo()` and `prettyPrintTo()`
* Removed `measureLength()` and `measurePrettyLength()`
2018-03-01 09:24:58 +01:00
7a2a64803a Don't use JsonBuffer to create or parse objects and arrays.
* Added DynamicJsonArray and StaticJsonArray
* Added DynamicJsonObject and StaticJsonObject
* Added DynamicJsonVariant and StaticJsonVariant
* Added deserializeJson()
* Removed JsonBuffer::parseArray(), parseObject() and parse()
* Removed JsonBuffer::createArray() and createObject()
2018-02-26 16:05:16 +01:00
baf5adcf33 Set version to 6.0.0 2018-02-26 16:00:44 +01:00
295 changed files with 6774 additions and 4416 deletions

1
.gitignore vendored
View File

@ -9,3 +9,4 @@
/fuzzing/*_fuzzer
/fuzzing/*_fuzzer.options
/fuzzing/*_fuzzer_seed_corpus.zip
.vs/

View File

@ -2,12 +2,6 @@ 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:
@ -37,7 +31,7 @@ matrix:
apt:
sources: ['ubuntu-toolchain-r-test']
packages: ['g++-5']
env: SCRIPT=cmake GCC=5
env: SCRIPT=cmake GCC=5 # SANITIZE=undefined
- compiler: gcc
addons:
apt:
@ -102,24 +96,16 @@ matrix:
env: SCRIPT=cmake CLANG=6.0
- compiler: gcc
env: SCRIPT=coverage
- os: osx
osx_image: xcode6.4
compiler: clang
env: SCRIPT=cmake
- os: osx
osx_image: xcode7.3
compiler: clang
env: SCRIPT=cmake
- os: osx
osx_image: xcode8.3
compiler: clang
env: SCRIPT=cmake
- os: osx
osx_image: xcode9.4
compiler: clang
env: SCRIPT=cmake
- os: osx
osx_image: xcode10
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:avr:uno
- env: SCRIPT=arduino VERSION=1.8.2 BOARD=arduino:samd:mkr1000
- env: SCRIPT=platformio BOARD=uno
- env: SCRIPT=platformio BOARD=esp01
- compiler: clang

View File

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

View File

@ -1,30 +1,71 @@
ArduinoJson: change log
=======================
HEAD
----
v6.0.1-beta
-----------
* `JsonObject::createNestedObject()` returns `JsonObject::invalid()` if key is null (issue #1891)
* `JsonObject::createNestedArray()` returns `JsonArray::invalid()` if key is null
* Fixed conflicts with `isnan()` and `isinf()` macros (issue #752)
v5.13.5
-------
v6.0.0-beta
-----------
* Fixed warning "unused variable" with GCC 4.4 (issue #912)
* Fixed warning "maybe uninitialized" (issue #909)
* Added an clear message for `StaticJsonDocument`, `DynamicJsonDocument`...
* 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
v5.13.4
-------
* Removed spurious files in the Particle library
v5.13.3
-------
* Improved float serialization when `-fsingle-precision-constant` is used
* Fixed `JsonVariant::is<int>()` that returned true for empty strings
* Fixed `JsonVariant::is<String>()` (closes #763)
> ### 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);
> ```
v5.13.2
-------
@ -445,51 +486,3 @@ 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/).

View File

@ -1,5 +1,5 @@
# ArduinoJson - arduinojson.org
# Copyright Benoit Blanchon 2014-2019
# Copyright Benoit Blanchon 2014-2018
# MIT License
cmake_minimum_required(VERSION 3.0)

View File

@ -1,7 +1,7 @@
The MIT License (MIT)
---------------------
Copyright © 2014-2019 Benoit BLANCHON
Copyright © 2014-2018 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:

View File

@ -2,11 +2,7 @@
---
[![arduino-library-badge](https://www.ardu-badge.com/badge/ArduinoJson.svg?version=5.13.5)](https://www.ardu-badge.com/ArduinoJson/5.13.5)
[![Build Status](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/master?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/master)
[![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=master)](https://travis-ci.org/bblanchon/ArduinoJson)
[![Coverage Status](https://img.shields.io/coveralls/bblanchon/ArduinoJson.svg)](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master)
[![Star this project](http://githubbadges.com/star.svg?user=bblanchon&repo=ArduinoJson&style=flat&color=fff&background=007ec6)](https://github.com/bblanchon/ArduinoJson)
[![Build status](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/master?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/master) [![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=master)](https://travis-ci.org/bblanchon/ArduinoJson) [![Coverage Status](https://img.shields.io/coveralls/bblanchon/ArduinoJson.svg)](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master) [![Star this project](http://githubbadges.com/star.svg?user=bblanchon&repo=ArduinoJson&style=flat&color=fff&background=007ec6)](https://github.com/bblanchon/ArduinoJson)
ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
@ -14,6 +10,7 @@ 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)
@ -63,10 +60,10 @@ Here is a program that parses a JSON document with ArduinoJson.
```c++
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(json);
DynamicJsonDocument doc;
deserializeJson(doc, json);
JsonObject& root = doc.as<JsonObject>();
const char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
@ -80,9 +77,9 @@ See the [tutorial on arduinojson.org](https://arduinojson.org/doc/decoding/?utm_
Here is a program that generates a JSON document with ArduinoJson:
```c++
StaticJsonBuffer<200> jsonBuffer;
DynamicJsonDocument doc;
JsonObject& root = jsonBuffer.createObject();
JsonObject& root = doc.to<JsonObject>();
root["sensor"] = "gps";
root["time"] = 1351824120;
@ -90,7 +87,7 @@ JsonArray& data = root.createNestedArray("data");
data.add(48.756080);
data.add(2.302038);
root.printTo(Serial);
serializeJson(doc, Serial);
// This prints:
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
```

View File

@ -1,4 +1,4 @@
version: 5.13.5.{build}
version: 6.0.1.{build}
environment:
matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
//
// This example shows how to store your project configuration in a file.
@ -29,17 +29,19 @@ void loadConfiguration(const char *filename, Config &config) {
// Open file for reading
File file = SD.open(filename);
// Allocate the memory pool on the stack.
// Don't forget to change the capacity to match your JSON document.
// 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.
StaticJsonBuffer<512> jsonBuffer;
StaticJsonDocument<512> doc;
// Parse the root object
JsonObject &root = jsonBuffer.parseObject(file);
if (!root.success())
// Deserialize the JSON document
DeserializationError error = deserializeJson(doc, file);
if (error)
Serial.println(F("Failed to read file, using default configuration"));
// Get the root object in the document
JsonObject &root = doc.as<JsonObject>();
// Copy values from the JsonObject to the Config
config.port = root["port"] | 2731;
strlcpy(config.hostname, // <- destination
@ -62,20 +64,20 @@ void saveConfiguration(const char *filename, const Config &config) {
return;
}
// 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;
// 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;
// Parse the root object
JsonObject &root = jsonBuffer.createObject();
// Make our document contain an object
JsonObject &root = doc.to<JsonObject>();
// Set the values
// Set the values in the object
root["hostname"] = config.hostname;
root["port"] = config.port;
// Serialize JSON to file
if (root.printTo(file) == 0) {
if (serializeJson(doc, file) == 0) {
Serial.println(F("Failed to write to file"));
}
@ -133,12 +135,12 @@ void loop() {
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// The website 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.
// Please check it out at: https://arduinojson.org/
//
// 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 ❤❤❤❤❤
// Please check it out at: https://arduinojson.org/book/

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
//
// This example shows how to generate a JSON document with ArduinoJson.
@ -11,24 +11,20 @@ void setup() {
Serial.begin(9600);
while (!Serial) continue;
// Memory pool for JSON object tree.
// Allocate the JSON document
//
// Inside the brackets, 200 is the size of the pool in bytes.
// Don't forget to change this value to match your JSON document.
// Inside the brackets, 200 is the RAM allocated to this document.
// Don't forget to change this value to match your requirement.
// Use arduinojson.org/assistant to compute the capacity.
StaticJsonBuffer<200> jsonBuffer;
StaticJsonDocument<200> doc;
// StaticJsonBuffer allocates memory on the stack, it can be
// replaced by DynamicJsonBuffer which allocates in the heap.
// StaticJsonObject allocates memory on the stack, it can be
// replaced by DynamicJsonDocument which allocates in the heap.
//
// DynamicJsonBuffer jsonBuffer(200);
// DynamicJsonDocument doc(200);
// 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();
// Make our document be an object
JsonObject& root = doc.to<JsonObject>();
// Add values in the object
//
@ -37,21 +33,19 @@ void setup() {
root["sensor"] = "gps";
root["time"] = 1351824120;
// Add a nested array.
// Add an array.
//
// 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);
root.printTo(Serial);
serializeJson(root, Serial);
// This prints:
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
Serial.println();
root.prettyPrintTo(Serial);
serializeJsonPretty(root, Serial);
// This prints:
// {
// "sensor": "gps",
@ -70,12 +64,12 @@ void loop() {
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// The website arduinojson.org contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// serialization problem.
// Please check it out at: https://arduinojson.org/
//
// 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 ❤❤❤❤❤
// Please check it out at: https://arduinojson.org/book/

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
//
// This example shows how to parse a JSON document in an HTTP response.
@ -70,19 +70,21 @@ void setup() {
return;
}
// Allocate JsonBuffer
// Allocate the JSON document
// Use arduinojson.org/assistant to compute the capacity.
const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60;
DynamicJsonBuffer jsonBuffer(capacity);
DynamicJsonDocument doc(capacity);
// Parse JSON object
JsonObject& root = jsonBuffer.parseObject(client);
if (!root.success()) {
Serial.println(F("Parsing failed!"));
DeserializationError error = deserializeJson(doc, client);
if (error) {
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.c_str());
return;
}
// Extract values
JsonObject& root = doc.as<JsonObject>();
Serial.println(F("Response:"));
Serial.println(root["sensor"].as<char*>());
Serial.println(root["time"].as<char*>());
@ -100,13 +102,13 @@ void loop() {
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// The website arduinojson.org contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// serialization problem.
// Please check it out at: https://arduinojson.org/
//
// 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 ❤❤❤❤❤
// Please check it out at: https://arduinojson.org/book/

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// 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;
// Memory pool for JSON object tree.
// Allocate the JSON document
//
// Inside the brackets, 200 is the size of the pool in bytes.
// 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.
StaticJsonBuffer<200> jsonBuffer;
StaticJsonDocument<200> doc;
// StaticJsonBuffer allocates memory on the stack, it can be
// replaced by DynamicJsonBuffer which allocates in the heap.
// StaticJsonDocument<N> allocates memory on the stack, it can be
// replaced by DynamicJsonObject which allocates in the heap.
//
// DynamicJsonBuffer jsonBuffer(200);
// DynamicJsonObject doc(200);
// JSON input string.
//
@ -31,19 +31,19 @@ void setup() {
char json[] =
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
// 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);
// Deserialize the JSON document
DeserializationError error = deserializeJson(doc, json);
// Test if parsing succeeds.
if (!root.success()) {
Serial.println("parseObject() failed");
if (error) {
Serial.print(F("deserializeJson() 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.
@ -67,12 +67,12 @@ void loop() {
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// The website arduinojson.org contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// deserialization problem.
// Please check it out at: https://arduinojson.org/
//
// 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 ❤❤❤❤❤
// Please check it out at: https://arduinojson.org/book/

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
//
// This example shows how to implement an HTTP server that sends JSON document
@ -51,12 +51,12 @@ void loop() {
// Read the request (we ignore the content in this example)
while (client.available()) client.read();
// Allocate JsonBuffer
// Allocate the JSON document
// Use arduinojson.org/assistant to compute the capacity.
StaticJsonBuffer<500> jsonBuffer;
StaticJsonDocument<500> doc;
// Create the root object
JsonObject& root = jsonBuffer.createObject();
// Make our document represent an object
JsonObject& root = doc.to<JsonObject>();
// Create the "analog" array
JsonArray& analogValues = root.createNestedArray("analog");
@ -79,7 +79,7 @@ void loop() {
}
Serial.print(F("Sending: "));
root.printTo(Serial);
serializeJson(root, Serial);
Serial.println();
// Write response headers
@ -89,7 +89,7 @@ void loop() {
client.println();
// Write JSON document
root.prettyPrintTo(client);
serializeJsonPretty(root, client);
// Disconnect
client.stop();
@ -98,12 +98,12 @@ void loop() {
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// The website arduinojson.org contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// serialization problem.
// Please check it out at: https://arduinojson.org/
//
// 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 ❤❤❤❤❤
// Please check it out at: https://arduinojson.org/book/

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
//
// This example shows how to send a JSON document to a UDP socket.
@ -43,12 +43,12 @@ void setup() {
}
void loop() {
// Allocate JsonBuffer
// Allocate the JSON document
// Use arduinojson.org/assistant to compute the capacity.
StaticJsonBuffer<500> jsonBuffer;
StaticJsonDocument<500> doc;
// Create the root object
JsonObject& root = jsonBuffer.createObject();
// Make our document represent an object
JsonObject& root = doc.to<JsonObject>();
// Create the "analog" array
JsonArray& analogValues = root.createNestedArray("analog");
@ -75,11 +75,11 @@ void loop() {
Serial.print(remoteIp);
Serial.print(F(" on port "));
Serial.println(remotePort);
root.printTo(Serial);
serializeJson(root, Serial);
// Send UDP packet
udp.beginPacket(remoteIp, remotePort);
root.printTo(udp);
serializeJson(root, udp);
udp.println();
udp.endPacket();
@ -90,12 +90,12 @@ void loop() {
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// The website arduinojson.org contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// serialization problem.
// Please check it out at: https://arduinojson.org/
//
// 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 ❤❤❤❤❤
// Please check it out at: https://arduinojson.org/book/

View File

@ -0,0 +1,91 @@
// 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
}
// See also
// --------
//
// The website arduinojson.org contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// deserialization problem.
// Please check it out at: https://arduinojson.org/
//
// 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.
// Please check it out at: https://arduinojson.org/book/

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
//
// This example shows the different ways you can use Flash strings with
@ -14,34 +14,34 @@
void setup() {
#ifdef PROGMEM // <- check that Flash strings are supported
DynamicJsonBuffer jsonBuffer;
DynamicJsonDocument doc;
// You can use a Flash String as your JSON input.
// WARNING: the content of the Flash String will be duplicated in the
// JsonBuffer.
JsonObject& root =
jsonBuffer.parseObject(F("{\"sensor\":\"gps\",\"time\":1351824120,"
"\"data\":[48.756080,2.302038]}"));
deserializeJson(doc, F("{\"sensor\":\"gps\",\"time\":1351824120,"
"\"data\":[48.756080,2.302038]}"));
JsonObject& obj = doc.as<JsonObject>();
// You can use a Flash String to get an element of a JsonObject
// No duplication is done.
long time = root[F("time")];
long time = obj[F("time")];
// You can use a Flash String to set an element of a JsonObject
// WARNING: the content of the Flash String will be duplicated in the
// JsonBuffer.
root[F("time")] = time;
obj[F("time")] = time;
// You can set a Flash String to a JsonObject or JsonArray:
// WARNING: the content of the Flash String will be duplicated in the
// JsonBuffer.
root["sensor"] = F("gps");
obj["sensor"] = F("gps");
// It works with RawJson too:
root["sensor"] = RawJson(F("\"gps\""));
obj["sensor"] = RawJson(F("\"gps\""));
// You can compare the content of a JsonVariant to a Flash String
if (root["sensor"] == F("gps")) {
if (obj["sensor"] == F("gps")) {
// ...
}
@ -59,12 +59,12 @@ void loop() {
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// The website arduinojson.org contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any memory
// problem.
// Please check it out at: https://arduinojson.org/
//
// 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 ❤❤❤❤❤
// Please check it out at: https://arduinojson.org/book/

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
//
// This example shows the different ways you can use String with ArduinoJson.
@ -11,50 +11,51 @@
#include <ArduinoJson.h>
void setup() {
DynamicJsonBuffer jsonBuffer;
DynamicJsonDocument doc;
// 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]}";
JsonObject& root = jsonBuffer.parseObject(input);
deserializeJson(doc, input);
JsonObject& obj = doc.as<JsonObject>();
// You can use a String to get an element of a JsonObject
// No duplication is done.
long time = root[String("time")];
long time = obj[String("time")];
// You can use a String to set an element of a JsonObject
// WARNING: the content of the String will be duplicated in the JsonBuffer.
root[String("time")] = time;
obj[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 = root["sensor"];
String sensor = obj["sensor"];
// Unfortunately, the following doesn't work (issue #118):
// sensor = root["sensor"]; // <- error "ambiguous overload for 'operator='"
// sensor = obj["sensor"]; // <- error "ambiguous overload for 'operator='"
// As a workaround, you need to replace by:
sensor = root["sensor"].as<String>();
sensor = obj["sensor"].as<String>();
// You can set a String to a JsonObject or JsonArray:
// WARNING: the content of the String will be duplicated in the JsonBuffer.
root["sensor"] = sensor;
obj["sensor"] = sensor;
// It works with RawJson too:
root["sensor"] = RawJson(sensor);
obj["sensor"] = RawJson(sensor);
// You can also concatenate strings
// WARNING: the content of the String will be duplicated in the JsonBuffer.
root[String("sen") + "sor"] = String("gp") + "s";
obj[String("sen") + "sor"] = String("gp") + "s";
// You can compare the content of a JsonObject with a String
if (root["sensor"] == sensor) {
if (obj["sensor"] == sensor) {
// ...
}
// Lastly, you can print the resulting JSON to a String
String output;
root.printTo(output);
serializeJson(doc, output);
}
void loop() {
@ -64,11 +65,11 @@ void loop() {
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// The website arduinojson.org contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any problem.
// Please check it out at: https://arduinojson.org/
//
// 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 ❤❤❤❤❤
// Please check it out at: https://arduinojson.org/book/

View File

@ -5,15 +5,18 @@ CXXFLAGS += -I../src
all: \
$(OUT)/json_fuzzer \
$(OUT)/json_fuzzer_seed_corpus.zip \
$(OUT)/json_fuzzer.options
$(OUT)/json_fuzzer.options \
$(OUT)/msgpack_fuzzer \
$(OUT)/msgpack_fuzzer_seed_corpus.zip \
$(OUT)/msgpack_fuzzer.options
$(OUT)/json_fuzzer: fuzzer.cpp $(shell find ../src -type f)
$(OUT)/%_fuzzer: %_fuzzer.cpp $(shell find ../src -type f)
$(CXX) $(CXXFLAGS) $< -o$@ $(LIB_FUZZING_ENGINE)
$(OUT)/json_fuzzer_seed_corpus.zip: seed_corpus/*
$(OUT)/%_fuzzer_seed_corpus.zip: %_seed_corpus/*
zip -j $@ $?
$(OUT)/json_fuzzer.options:
$(OUT)/%_fuzzer.options:
@echo "[libfuzzer]" > $@
@echo "max_len = 256" >> $@
@echo "timeout = 10" >> $@

View File

@ -1,26 +0,0 @@
#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;
}

11
fuzzing/json_fuzzer.cpp Normal file
View File

@ -0,0 +1,11 @@
#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 Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

View File

@ -0,0 +1,11 @@
#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.

View File

@ -0,0 +1 @@
<EFBFBD>

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD>hello<EFBFBD>world

View File

@ -0,0 +1 @@
<EFBFBD>

View File

@ -0,0 +1 @@


View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD>one<01>two

View File

@ -0,0 +1 @@
<EFBFBD>hello world

View File

@ -0,0 +1 @@
<EFBFBD>@H<><48>

View File

@ -0,0 +1 @@
<EFBFBD>@ !<21><><EFBFBD>o

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD><EFBFBD>

View File

@ -0,0 +1 @@
Ҷi<EFBFBD>.

View File

@ -0,0 +1 @@
<EFBFBD>4Vx<56><78><EFBFBD><EFBFBD>

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD>

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
<EFBFBD>

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
<EFBFBD>hello

View File

@ -0,0 +1 @@
<EFBFBD>

View File

@ -0,0 +1 @@
<EFBFBD>09

View File

@ -0,0 +1 @@
<EFBFBD>4Vx

View File

@ -0,0 +1 @@
<EFBFBD>4Vx<56><78><EFBFBD><EFBFBD>

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD>

View File

@ -1,15 +1,17 @@
add KEYWORD2
as KEYWORD2
createNestedArray KEYWORD2
createNestedObject KEYWORD2
deserializeJson KEYWORD2
deserializeMsgPack KEYWORD2
DynamicJsonDocument KEYWORD1
get KEYWORD2
JsonArray KEYWORD1
JsonObject KEYWORD1
JsonVariant KEYWORD1
StaticJsonBuffer KEYWORD1
DynamicJsonBuffer KEYWORD1
add KEYWORD2
createArray KEYWORD2
createNestedArray KEYWORD2
createNestedObject KEYWORD2
createObject KEYWORD2
parseArray KEYWORD2
parseObject KEYWORD2
prettyPrintTo KEYWORD2
printTo KEYWORD2
success KEYWORD2
serializeMsgPack KEYWORD2
serializeJson KEYWORD2
serializeJsonPretty KEYWORD2
set KEYWORD2
StaticJsonDocument KEYWORD1
to KEYWORD2

View File

@ -7,7 +7,7 @@
"type": "git",
"url": "https://github.com/bblanchon/ArduinoJson.git"
},
"version": "5.13.5",
"version": "6.0.1-beta",
"authors": {
"name": "Benoit Blanchon",
"url": "https://blog.benoitblanchon.fr"

View File

@ -1,9 +1,9 @@
name=ArduinoJson
version=5.13.5
version=6.0.1-beta
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, ✔ 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, ✔ 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.
category=Data Processing
url=https://arduinojson.org/?utm_source=meta&utm_medium=library.properties
architectures=*

42
scripts/create-size-graph.sh Executable file
View File

@ -0,0 +1,42 @@
#!/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

View File

@ -2,11 +2,16 @@
Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/xenial64"
config.vm.synced_folder "E:\\Git\\Arduino\\libraries\\ArduinoJson", "/host/ArduinoJson"
config.vm.synced_folder "../..", "/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
@ -18,10 +23,6 @@ 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

View File

@ -1,18 +0,0 @@
#!/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

View File

@ -1,4 +1,4 @@
#!/bin/sh -eux
#!/bin/bash -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,9 +6,13 @@ 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

View File

@ -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,11 +23,8 @@ fi
if [ -n "$SANITIZE" ]; then
export CXXFLAGS="-fsanitize=$SANITIZE"
BUILD_TYPE="Debug"
else
BUILD_TYPE="Release"
fi
$CMAKE -DCMAKE_BUILD_TYPE=$BUILD_TYPE .
$CMAKE .
$CMAKE --build .
$CTEST --output-on-failure .

View File

@ -1,20 +1,26 @@
#!/bin/bash -eux
ROOT_DIR=$(dirname $0)/../../
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"
INCLUDE_DIR=${ROOT_DIR}/src/
FUZZING_DIR=${ROOT_DIR}/fuzzing/
CXXFLAGS="-g -fprofile-instr-generate -fcoverage-mapping -fsanitize=address,fuzzer"
$CXX $CXXFLAGS -o json_fuzzer -I$INCLUDE_DIR $FUZZING_DIR/fuzzer.cpp
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"
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
clang++-${CLANG} ${CXXFLAGS} -o ${FUZZER} -I$INCLUDE_DIR ${FUZZER_CPP}
llvm-profdata-$CLANG merge -sparse json_fuzzer.profraw -o json_fuzzer.profdata
export ASAN_OPTIONS="detect_leaks=0"
export LLVM_PROFILE_FILE="${FUZZER}.profraw"
./${FUZZER} "$CORPUS_DIR" "$SEED_CORPUS_DIR" -max_total_time=30
llvm-cov-$CLANG report ./json_fuzzer -instr-profile=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

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once

View File

@ -1,21 +1,19 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "ArduinoJson/version.hpp"
#include "ArduinoJson/DynamicJsonBuffer.hpp"
#include "ArduinoJson/JsonArray.hpp"
#include "ArduinoJson/JsonObject.hpp"
#include "ArduinoJson/StaticJsonBuffer.hpp"
#include "ArduinoJson/DynamicJsonDocument.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"
#include "ArduinoJson/StaticJsonDocument.hpp"
#include "ArduinoJson/Deserialization/JsonParserImpl.hpp"
#include "ArduinoJson/JsonArrayImpl.hpp"
#include "ArduinoJson/JsonBufferImpl.hpp"
#include "ArduinoJson/JsonObjectImpl.hpp"
#include "ArduinoJson/JsonVariantImpl.hpp"
#include "ArduinoJson/Serialization/JsonSerializerImpl.hpp"
#include "ArduinoJson/compatibility.hpp"

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
@ -130,11 +130,6 @@
#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
@ -149,3 +144,13 @@
#if ARDUINOJSON_USE_LONG_LONG && ARDUINOJSON_USE_INT64
#error ARDUINOJSON_USE_LONG_LONG and ARDUINOJSON_USE_INT64 cannot be set together
#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
#endif

View File

@ -1,10 +1,10 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "IsBaseOf.hpp"
#include "../Polyfills/type_traits.hpp"
namespace ArduinoJson {
namespace Internals {
@ -12,6 +12,6 @@ namespace Internals {
class JsonVariantTag {};
template <typename T>
struct IsVariant : IsBaseOf<JsonVariantTag, T> {};
struct IsVariant : is_base_of<JsonVariantTag, T> {};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
@ -14,5 +14,5 @@ typedef double JsonFloat;
#else
typedef float JsonFloat;
#endif
} // namespace Internals
} // namespace ArduinoJson
}
}

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
@ -19,5 +19,5 @@ typedef unsigned _int64 JsonUInt;
typedef long JsonInteger;
typedef unsigned long JsonUInt;
#endif
} // namespace Internals
} // namespace ArduinoJson
}
}

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
@ -38,5 +38,5 @@ template <>
struct JsonVariantAs<const JsonObject> {
typedef const JsonObject& type;
};
} // namespace Internals
} // namespace ArduinoJson
}
}

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
@ -23,5 +23,5 @@ union JsonVariantContent {
JsonArray* asArray; // asArray cannot be null
JsonObject* asObject; // asObject cannot be null
};
} // namespace Internals
} // namespace ArduinoJson
}
}

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
@ -19,5 +19,5 @@ struct JsonVariantDefault<const T> : JsonVariantDefault<T> {};
template <typename T>
struct JsonVariantDefault<T&> : JsonVariantDefault<T> {};
} // namespace Internals
} // namespace ArduinoJson
}
}

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
@ -23,5 +23,5 @@ enum JsonVariantType {
JSON_OBJECT, // JsonVariant stores a pointer to a JsonObject
JSON_FLOAT // JsonVariant stores a JsonFloat
};
} // namespace Internals
} // namespace ArduinoJson
}
}

View File

@ -1,10 +1,10 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../JsonBuffer.hpp"
#include "../Memory/JsonBuffer.hpp"
#include "ListConstIterator.hpp"
#include "ListIterator.hpp"
@ -27,7 +27,7 @@ class List {
// 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) {}
explicit List(JsonBuffer *buf) : _buffer(buf), _firstNode(NULL) {}
// Returns true if the object is valid
// Would return false in the following situation:
@ -84,7 +84,15 @@ class List {
}
}
JsonBuffer &buffer() const {
return *_buffer;
}
protected:
void clear() {
_firstNode = 0;
}
JsonBuffer *_buffer;
private:

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
@ -46,5 +46,5 @@ class ListConstIterator {
private:
const ListNode<T> *_node;
};
} // namespace Internals
} // namespace ArduinoJson
}
}

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
@ -56,5 +56,5 @@ class ListIterator {
private:
ListNode<T> *_node;
};
} // namespace Internals
} // namespace ArduinoJson
}
}

View File

@ -1,12 +1,12 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include <stddef.h> // for NULL
#include "JsonBufferAllocated.hpp"
#include "../Memory/JsonBufferAllocated.hpp"
namespace ArduinoJson {
namespace Internals {

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
@ -20,5 +20,5 @@ class ReferenceType {
return this != &other;
}
};
} // namespace Internals
} // namespace ArduinoJson
}
}

View File

@ -1,13 +1,13 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../JsonBuffer.hpp"
#include "../JsonVariant.hpp"
#include "../StringTraits/StringTraits.hpp"
#include "../TypeTraits/EnableIf.hpp"
#include "../Memory/JsonBuffer.hpp"
#include "../Polyfills/type_traits.hpp"
#include "../Strings/StringTraits.hpp"
namespace ArduinoJson {
namespace Internals {
@ -23,7 +23,7 @@ struct ValueSaver {
template <typename Source>
struct ValueSaver<
Source, typename EnableIf<StringTraits<Source>::should_duplicate>::type> {
Source, typename enable_if<StringTraits<Source>::should_duplicate>::type> {
template <typename Destination>
static bool save(JsonBuffer* buffer, Destination& dest, Source source) {
if (!StringTraits<Source>::is_null(source)) {
@ -41,7 +41,7 @@ struct ValueSaver<
// const char*, const signed char*, const unsigned char*
template <typename Char>
struct ValueSaver<
Char*, typename EnableIf<!StringTraits<Char*>::should_duplicate>::type> {
Char*, typename enable_if<!StringTraits<Char*>::should_duplicate>::type> {
template <typename Destination>
static bool save(JsonBuffer*, Destination& dest, Char* source) {
dest = reinterpret_cast<const char*>(source);

View File

@ -0,0 +1,41 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
#include <Stream.h>
namespace ArduinoJson {
namespace Internals {
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 Internals
} // namespace ArduinoJson
#endif

View File

@ -0,0 +1,64 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ArduinoJson {
namespace Internals {
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 Internals
} // namespace ArduinoJson

View File

@ -1,61 +0,0 @@
// 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

View File

@ -0,0 +1,83 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#if ARDUINOJSON_ENABLE_STD_STREAM
#include <ostream>
#endif
namespace ArduinoJson {
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

View File

@ -0,0 +1,56 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#if ARDUINOJSON_ENABLE_PROGMEM
namespace ArduinoJson {
namespace Internals {
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 Internals
} // namespace ArduinoJson
#endif

View File

@ -0,0 +1,34 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ArduinoJson {
namespace Internals {
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 Internals
} // namespace ArduinoJson

View File

@ -1,102 +0,0 @@
// 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

View File

@ -1,189 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "Comments.hpp"
#include "JsonParser.hpp"
template <typename TReader, typename TWriter>
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::eat(
TReader &reader, char charToSkip) {
skipSpacesAndComments(reader);
if (reader.current() != charToSkip) return false;
reader.move();
return true;
}
template <typename TReader, typename TWriter>
inline bool
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseAnythingTo(
JsonVariant *destination) {
skipSpacesAndComments(_reader);
switch (_reader.current()) {
case '[':
return parseArrayTo(destination);
case '{':
return parseObjectTo(destination);
default:
return parseStringTo(destination);
}
}
template <typename TReader, typename TWriter>
inline ArduinoJson::JsonArray &
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseArray() {
if (_nestingLimit == 0) return JsonArray::invalid();
_nestingLimit--;
// Create an empty array
JsonArray &array = _buffer->createArray();
// Check opening braket
if (!eat('[')) goto ERROR_MISSING_BRACKET;
if (eat(']')) goto SUCCESS_EMPTY_ARRAY;
// Read each value
for (;;) {
// 1 - Parse value
JsonVariant value;
if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE;
if (!array.add(value)) goto ERROR_NO_MEMORY;
// 2 - More values?
if (eat(']')) goto SUCCES_NON_EMPTY_ARRAY;
if (!eat(',')) goto ERROR_MISSING_COMMA;
}
SUCCESS_EMPTY_ARRAY:
SUCCES_NON_EMPTY_ARRAY:
_nestingLimit++;
return array;
ERROR_INVALID_VALUE:
ERROR_MISSING_BRACKET:
ERROR_MISSING_COMMA:
ERROR_NO_MEMORY:
return JsonArray::invalid();
}
template <typename TReader, typename TWriter>
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseArrayTo(
JsonVariant *destination) {
JsonArray &array = parseArray();
if (!array.success()) return false;
*destination = array;
return true;
}
template <typename TReader, typename TWriter>
inline ArduinoJson::JsonObject &
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseObject() {
if (_nestingLimit == 0) return JsonObject::invalid();
_nestingLimit--;
// Create an empty object
JsonObject &object = _buffer->createObject();
// Check opening brace
if (!eat('{')) goto ERROR_MISSING_BRACE;
if (eat('}')) goto SUCCESS_EMPTY_OBJECT;
// Read each key value pair
for (;;) {
// 1 - Parse key
const char *key = parseString();
if (!key) goto ERROR_INVALID_KEY;
if (!eat(':')) goto ERROR_MISSING_COLON;
// 2 - Parse value
JsonVariant value;
if (!parseAnythingTo(&value)) goto ERROR_INVALID_VALUE;
if (!object.set(key, value)) goto ERROR_NO_MEMORY;
// 3 - More keys/values?
if (eat('}')) goto SUCCESS_NON_EMPTY_OBJECT;
if (!eat(',')) goto ERROR_MISSING_COMMA;
}
SUCCESS_EMPTY_OBJECT:
SUCCESS_NON_EMPTY_OBJECT:
_nestingLimit++;
return object;
ERROR_INVALID_KEY:
ERROR_INVALID_VALUE:
ERROR_MISSING_BRACE:
ERROR_MISSING_COLON:
ERROR_MISSING_COMMA:
ERROR_NO_MEMORY:
return JsonObject::invalid();
}
template <typename TReader, typename TWriter>
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseObjectTo(
JsonVariant *destination) {
JsonObject &object = parseObject();
if (!object.success()) return false;
*destination = object;
return true;
}
template <typename TReader, typename TWriter>
inline const char *
ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseString() {
typename RemoveReference<TWriter>::type::String str = _writer.startString();
skipSpacesAndComments(_reader);
char c = _reader.current();
if (isQuote(c)) { // quotes
_reader.move();
char stopChar = c;
for (;;) {
c = _reader.current();
if (c == '\0') break;
_reader.move();
if (c == stopChar) break;
if (c == '\\') {
// replace char
c = Encoding::unescapeChar(_reader.current());
if (c == '\0') break;
_reader.move();
}
str.append(c);
}
} else { // no quotes
for (;;) {
if (!canBeInNonQuotedString(c)) break;
_reader.move();
str.append(c);
c = _reader.current();
}
}
return str.c_str();
}
template <typename TReader, typename TWriter>
inline bool ArduinoJson::Internals::JsonParser<TReader, TWriter>::parseStringTo(
JsonVariant *destination) {
bool hasQuotes = isQuote(_reader.current());
const char *value = parseString();
if (value == NULL) return false;
if (hasQuotes) {
*destination = value;
} else {
*destination = RawJson(value);
}
return true;
}

View File

@ -0,0 +1,40 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#if ARDUINOJSON_ENABLE_STD_STREAM
#include <istream>
namespace ArduinoJson {
namespace Internals {
class StdStreamReader {
std::istream& _stream;
char _current;
public:
explicit StdStreamReader(std::istream& stream)
: _stream(stream), _current(0) {}
bool ended() const {
return _stream.eof();
}
char read() {
return static_cast<char>(_stream.get());
}
private:
StdStreamReader& operator=(const StdStreamReader&); // Visual Studio C4512
};
inline StdStreamReader makeReader(std::istream& input) {
return StdStreamReader(input);
}
} // namespace Internals
} // namespace ArduinoJson
#endif

View File

@ -0,0 +1,82 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../StringStorage/StringStorage.hpp"
#include "./ArduinoStreamReader.hpp"
#include "./CharPointerReader.hpp"
#include "./DeserializationError.hpp"
#include "./FlashStringReader.hpp"
#include "./IteratorReader.hpp"
#include "./StdStreamReader.hpp"
namespace ArduinoJson {
namespace Internals {
template <template <typename, typename> class TDeserializer,
typename TJsonBuffer, typename TReader, typename TWriter>
TDeserializer<TReader, TWriter> makeDeserializer(TJsonBuffer *buffer,
TReader reader, TWriter writer,
uint8_t nestingLimit) {
return TDeserializer<TReader, TWriter>(buffer, reader, writer, nestingLimit);
}
// DeserializationError deserialize(TDocument& doc, TString input);
// TDocument = DynamicJsonDocument, StaticJsonDocument
// TString = const std::string&, const String&
template <template <typename, typename> class TDeserializer, typename TDocument,
typename TString>
typename Internals::enable_if<!Internals::is_array<TString>::value,
DeserializationError>::type
deserialize(TDocument &doc, const TString &input) {
using namespace Internals;
return makeDeserializer<TDeserializer>(&doc.buffer(), makeReader(input),
makeStringStorage(doc.buffer(), input),
doc.nestingLimit)
.parse(doc.template to<JsonVariant>());
}
//
// DeserializationError deserialize(TDocument& doc, TChar* input);
// TDocument = DynamicJsonDocument, StaticJsonDocument
// TChar* = char*, const char*, const FlashStringHelper*
template <template <typename, typename> class TDeserializer, typename TDocument,
typename TChar>
DeserializationError deserialize(TDocument &doc, TChar *input) {
using namespace Internals;
return makeDeserializer<TDeserializer>(&doc.buffer(), makeReader(input),
makeStringStorage(doc.buffer(), input),
doc.nestingLimit)
.parse(doc.template to<JsonVariant>());
}
//
// DeserializationError deserialize(TDocument& doc, TChar* input, size_t
// inputSize);
// TDocument = DynamicJsonDocument, StaticJsonDocument
// TChar* = char*, const char*, const FlashStringHelper*
template <template <typename, typename> class TDeserializer, typename TDocument,
typename TChar>
DeserializationError deserialize(TDocument &doc, TChar *input,
size_t inputSize) {
using namespace Internals;
return makeDeserializer<TDeserializer>(
&doc.buffer(), makeReader(input, inputSize),
makeStringStorage(doc.buffer(), input), doc.nestingLimit)
.parse(doc.template to<JsonVariant>());
}
//
// DeserializationError deserialize(TDocument& doc, TStream input);
// TDocument = DynamicJsonDocument, StaticJsonDocument
// TStream = std::istream&, Stream&
template <template <typename, typename> class TDeserializer, typename TDocument,
typename TStream>
DeserializationError deserialize(TDocument &doc, TStream &input) {
using namespace Internals;
return makeDeserializer<TDeserializer>(&doc.buffer(), makeReader(input),
makeStringStorage(doc.buffer(), input),
doc.nestingLimit)
.parse(doc.template to<JsonVariant>());
}
} // namespace Internals
} // namespace ArduinoJson

View File

@ -0,0 +1,86 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonArray.hpp"
#include "JsonObject.hpp"
#include "JsonVariant.hpp"
#include "Memory/DynamicJsonBuffer.hpp"
namespace ArduinoJson {
class DynamicJsonDocument {
Internals::DynamicJsonBuffer _buffer;
JsonVariant _root;
public:
uint8_t nestingLimit;
DynamicJsonDocument() : nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
DynamicJsonDocument(size_t capacity)
: _buffer(capacity), nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
template <typename T>
bool is() const {
return _root.is<T>();
}
template <typename T>
typename Internals::JsonVariantAs<T>::type as() const {
return _root.as<T>();
}
// JsonObject& to<JsonObject>()
template <typename T>
typename Internals::enable_if<Internals::is_same<T, JsonObject>::value,
JsonObject&>::type
to() {
clear();
JsonObject* object = new (&_buffer) JsonObject(&_buffer);
if (!object) return JsonObject::invalid();
_root = object;
return *object;
}
// JsonArray& to<JsonArray>()
template <typename T>
typename Internals::enable_if<Internals::is_same<T, JsonArray>::value,
JsonArray&>::type
to() {
clear();
JsonArray* array = new (&_buffer) JsonArray(&_buffer);
if (!array) return JsonArray::invalid();
_root = array;
return *array;
}
// JsonVariant& to<JsonVariant>()
template <typename T>
typename Internals::enable_if<Internals::is_same<T, JsonVariant>::value,
T&>::type
to() {
clear();
return _root;
}
Internals::DynamicJsonBuffer& buffer() {
return _buffer;
}
void clear() {
_buffer.clear();
_root = JsonVariant();
}
size_t memoryUsage() const {
return _buffer.size();
}
template <typename Visitor>
void visit(Visitor& visitor) const {
return _root.visit(visitor);
}
};
} // namespace ArduinoJson

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
@ -7,7 +7,7 @@
namespace ArduinoJson {
namespace Internals {
class Encoding {
class EscapeSequence {
public:
// Optimized for code size on a 8-bit AVR
static char escapeChar(char c) {

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
@ -8,7 +8,7 @@ namespace ArduinoJson {
namespace Internals {
// Decorator on top of Print to allow indented output.
// This class is used by JsonPrintable::prettyPrintTo() but can also be used
// This class is used by serializeJsonPretty() but can also be used
// for your own purpose, like logging.
template <typename Print>
class IndentedPrint {

View File

@ -0,0 +1,318 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Deserialization/deserialize.hpp"
#include "../JsonVariant.hpp"
#include "../Memory/JsonBuffer.hpp"
#include "../Polyfills/type_traits.hpp"
#include "./EscapeSequence.hpp"
namespace ArduinoJson {
namespace Internals {
template <typename TReader, typename TStringStorage>
class JsonDeserializer {
public:
JsonDeserializer(JsonBuffer *buffer, TReader reader,
TStringStorage stringStorage, uint8_t nestingLimit)
: _buffer(buffer),
_reader(reader),
_stringStorage(stringStorage),
_nestingLimit(nestingLimit),
_loaded(false) {}
DeserializationError parse(JsonVariant &variant) {
DeserializationError err = skipSpacesAndComments();
if (err) return err;
switch (current()) {
case '[':
return parseArray(variant);
case '{':
return parseObject(variant);
default:
return parseValue(variant);
}
}
private:
JsonDeserializer &operator=(const JsonDeserializer &); // non-copiable
char current() {
if (!_loaded) {
if (_reader.ended())
_current = 0;
else
_current = _reader.read();
_loaded = true;
}
return _current;
}
void move() {
_loaded = false;
}
FORCE_INLINE bool eat(char charToSkip) {
if (current() != charToSkip) return false;
move();
return true;
}
DeserializationError parseArray(JsonVariant &variant) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
JsonArray *array = new (_buffer) JsonArray(_buffer);
if (!array) return DeserializationError::NoMemory;
variant = array;
// Check opening braket
if (!eat('[')) return DeserializationError::InvalidInput;
// Skip spaces
DeserializationError err = skipSpacesAndComments();
if (err) return err;
// Empty array?
if (eat(']')) return DeserializationError::Ok;
// Read each value
for (;;) {
// 1 - Parse value
JsonVariant value;
_nestingLimit--;
err = parse(value);
_nestingLimit++;
if (err) return err;
if (!array->add(value)) return DeserializationError::NoMemory;
// 2 - Skip spaces
err = skipSpacesAndComments();
if (err) return err;
// 3 - More values?
if (eat(']')) return DeserializationError::Ok;
if (!eat(',')) return DeserializationError::InvalidInput;
}
}
DeserializationError parseObject(JsonVariant &variant) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
JsonObject *object = new (_buffer) JsonObject(_buffer);
if (!object) return DeserializationError::NoMemory;
variant = object;
// Check opening brace
if (!eat('{')) return DeserializationError::InvalidInput;
// Skip spaces
DeserializationError err = skipSpacesAndComments();
if (err) return err;
// Empty object?
if (eat('}')) return DeserializationError::Ok;
// Read each key value pair
for (;;) {
// Parse key
const char *key;
err = parseString(&key);
if (err) return err;
// Skip spaces
err = skipSpacesAndComments();
if (err) return err;
// Colon
if (!eat(':')) return DeserializationError::InvalidInput;
// Parse value
JsonVariant value;
_nestingLimit--;
err = parse(value);
_nestingLimit++;
if (err) return err;
if (!object->set(key, value)) return DeserializationError::NoMemory;
// Skip spaces
err = skipSpacesAndComments();
if (err) return err;
// More keys/values?
if (eat('}')) return DeserializationError::Ok;
if (!eat(',')) return DeserializationError::InvalidInput;
// Skip spaces
err = skipSpacesAndComments();
if (err) return err;
}
}
DeserializationError parseValue(JsonVariant &variant) {
bool hasQuotes = isQuote(current());
const char *value;
DeserializationError error = parseString(&value);
if (error) return error;
if (hasQuotes) {
variant = value;
} else {
variant = RawJson(value);
}
return DeserializationError::Ok;
}
DeserializationError parseString(const char **result) {
typename remove_reference<TStringStorage>::type::String str =
_stringStorage.startString();
char c = current();
if (c == '\0') return DeserializationError::IncompleteInput;
if (isQuote(c)) { // quotes
move();
char stopChar = c;
for (;;) {
c = current();
move();
if (c == stopChar) break;
if (c == '\0') return DeserializationError::IncompleteInput;
if (c == '\\') {
c = current();
if (c == '\0') return DeserializationError::IncompleteInput;
if (c == 'u') return DeserializationError::NotSupported;
// replace char
c = EscapeSequence::unescapeChar(c);
if (c == '\0') return DeserializationError::InvalidInput;
move();
}
str.append(c);
}
} else if (canBeInNonQuotedString(c)) { // no quotes
do {
move();
str.append(c);
c = current();
} while (canBeInNonQuotedString(c));
} else {
return DeserializationError::InvalidInput;
}
*result = str.c_str();
if (*result == NULL) return DeserializationError::NoMemory;
return DeserializationError::Ok;
}
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 == '\"';
}
DeserializationError skipSpacesAndComments() {
for (;;) {
switch (current()) {
// end of string
case '\0':
return DeserializationError::IncompleteInput;
// spaces
case ' ':
case '\t':
case '\r':
case '\n':
move();
continue;
// comments
case '/':
move(); // skip '/'
switch (current()) {
// block comment
case '*': {
move(); // skip '*'
bool wasStar = false;
for (;;) {
char c = current();
if (c == '\0') return DeserializationError::IncompleteInput;
if (c == '/' && wasStar) {
move();
break;
}
wasStar = c == '*';
move();
}
break;
}
// trailing comment
case '/':
// no need to skip "//"
for (;;) {
move();
char c = current();
if (c == '\0') return DeserializationError::IncompleteInput;
if (c == '\n') break;
}
break;
// not a comment, just a '/'
default:
return DeserializationError::InvalidInput;
}
break;
default:
return DeserializationError::Ok;
}
}
}
JsonBuffer *_buffer;
TReader _reader;
TStringStorage _stringStorage;
uint8_t _nestingLimit;
char _current;
bool _loaded;
};
} // namespace Internals
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, const TInput &input) {
using namespace Internals;
return deserialize<JsonDeserializer>(doc, input);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, TInput *input) {
using namespace Internals;
return deserialize<JsonDeserializer>(doc, input);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, TInput *input,
size_t inputSize) {
using namespace Internals;
return deserialize<JsonDeserializer>(doc, input, inputSize);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, TInput &input) {
using namespace Internals;
return deserialize<JsonDeserializer>(doc, input);
}
} // namespace ArduinoJson

View File

@ -0,0 +1,139 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Serialization/measure.hpp"
#include "../Serialization/serialize.hpp"
#include "./JsonWriter.hpp"
namespace ArduinoJson {
namespace Internals {
template <typename TPrint>
class JsonSerializer {
public:
JsonSerializer(TPrint &destination) : _writer(destination) {}
void acceptFloat(JsonFloat value) {
_writer.writeFloat(value);
}
void acceptArray(const JsonArray &array) {
_writer.beginArray();
JsonArray::const_iterator it = array.begin();
while (it != array.end()) {
it->visit(*this);
++it;
if (it == array.end()) break;
_writer.writeComma();
}
_writer.endArray();
}
void acceptObject(const JsonObject &object) {
_writer.beginObject();
JsonObject::const_iterator it = object.begin();
while (it != object.end()) {
_writer.writeString(it->key);
_writer.writeColon();
it->value.visit(*this);
++it;
if (it == object.end()) break;
_writer.writeComma();
}
_writer.endObject();
}
void acceptString(const char *value) {
_writer.writeString(value);
}
void acceptRawJson(const char *value) {
_writer.writeRaw(value);
}
void acceptNegativeInteger(JsonUInt value) {
_writer.writeRaw('-');
_writer.writeInteger(value);
}
void acceptPositiveInteger(JsonUInt value) {
_writer.writeInteger(value);
}
void acceptBoolean(bool value) {
_writer.writeBoolean(value);
}
void acceptUndefined() {}
size_t bytesWritten() const {
return _writer.bytesWritten();
}
private:
JsonWriter<TPrint> _writer;
};
} // namespace Internals
template <typename TSource, typename TDestination>
size_t serializeJson(TSource &source, TDestination &destination) {
using namespace Internals;
return serialize<JsonSerializer>(source, destination);
}
template <typename TSource>
size_t serializeJson(const TSource &source, char *buffer, size_t bufferSize) {
using namespace Internals;
return serialize<JsonSerializer>(source, buffer, bufferSize);
}
template <typename TSource>
size_t measureJson(const TSource &source) {
using namespace Internals;
return measure<JsonSerializer>(source);
}
#if ARDUINOJSON_ENABLE_STD_STREAM
inline std::ostream &operator<<(std::ostream &os, const JsonArray &source) {
serializeJson(source, os);
return os;
}
inline std::ostream &operator<<(std::ostream &os, const JsonObject &source) {
serializeJson(source, os);
return os;
}
inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) {
serializeJson(source, os);
return os;
}
namespace Internals {
inline std::ostream &operator<<(std::ostream &os,
const JsonArraySubscript &source) {
serializeJson(source, os);
return os;
}
template <typename TKey>
inline std::ostream &operator<<(std::ostream &os,
const JsonObjectSubscript<TKey> &source) {
serializeJson(source, os);
return os;
}
} // namespace Internals
#endif
} // namespace ArduinoJson

View File

@ -1,14 +1,14 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include <stdint.h>
#include "../Data/Encoding.hpp"
#include "../Data/JsonInteger.hpp"
#include "../Numbers/FloatParts.hpp"
#include "../Polyfills/attributes.hpp"
#include "../Serialization/FloatParts.hpp"
#include "./EscapeSequence.hpp"
namespace ArduinoJson {
namespace Internals {
@ -26,8 +26,6 @@ class JsonWriter {
explicit JsonWriter(Print &sink) : _sink(sink), _length(0) {}
// Returns the number of bytes sent to the Print implementation.
// This is very handy for implementations of printTo() that must return the
// number of bytes written.
size_t bytesWritten() const {
return _length;
}
@ -68,7 +66,7 @@ class JsonWriter {
}
void writeChar(char c) {
char specialChar = Encoding::escapeChar(c);
char specialChar = EscapeSequence::escapeChar(c);
if (specialChar) {
writeRaw('\\');
writeRaw(specialChar);
@ -79,14 +77,14 @@ class JsonWriter {
template <typename TFloat>
void writeFloat(TFloat value) {
if (isNaN(value)) return writeRaw("NaN");
if (isnan(value)) return writeRaw("NaN");
if (value < 0.0) {
writeRaw('-');
value = -value;
}
if (isInfinity(value)) return writeRaw("Infinity");
if (isinf(value)) return writeRaw("Infinity");
FloatParts<TFloat> parts(value);

View File

@ -0,0 +1,57 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Serialization/measure.hpp"
#include "../Serialization/serialize.hpp"
#include "./IndentedPrint.hpp"
#include "./JsonSerializer.hpp"
#include "./Prettyfier.hpp"
namespace ArduinoJson {
namespace Internals {
template <typename TPrint>
class PrettyJsonSerializer_Base {
public:
PrettyJsonSerializer_Base(TPrint &output)
: _indentedPrint(output), _prettyfier(_indentedPrint) {}
protected:
IndentedPrint<TPrint> _indentedPrint;
Prettyfier<TPrint> _prettyfier;
};
template <typename TPrint>
class PrettyJsonSerializer : PrettyJsonSerializer_Base<TPrint>,
public JsonSerializer<Prettyfier<TPrint> > {
public:
PrettyJsonSerializer(TPrint &output)
: PrettyJsonSerializer_Base<TPrint>(output),
JsonSerializer<Prettyfier<TPrint> >(
PrettyJsonSerializer_Base<TPrint>::_prettyfier) {}
};
} // namespace Internals
template <typename TSource, typename TDestination>
size_t serializeJsonPretty(TSource &source, TDestination &destination) {
using namespace Internals;
return serialize<PrettyJsonSerializer>(source, destination);
}
template <typename TSource>
size_t serializeJsonPretty(const TSource &source, char *buffer,
size_t bufferSize) {
using namespace Internals;
return serialize<PrettyJsonSerializer>(source, buffer, bufferSize);
}
template <typename TSource>
size_t measureJsonPretty(const TSource &source) {
using namespace Internals;
return measure<PrettyJsonSerializer>(source);
}
} // namespace ArduinoJson

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
@ -129,5 +129,5 @@ class Prettyfier {
IndentedPrint<Print>& _sink;
bool _inString;
};
} // namespace Internals
} // namespace ArduinoJson
}
}

View File

@ -1,20 +1,16 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Data/JsonBufferAllocated.hpp"
#include "Data/List.hpp"
#include "Data/ReferenceType.hpp"
#include "Data/ValueSaver.hpp"
#include "JsonVariant.hpp"
#include "Serialization/JsonPrintable.hpp"
#include "StringTraits/StringTraits.hpp"
#include "TypeTraits/EnableIf.hpp"
#include "TypeTraits/IsArray.hpp"
#include "TypeTraits/IsFloatingPoint.hpp"
#include "TypeTraits/IsSame.hpp"
#include "Memory/JsonBufferAllocated.hpp"
#include "Polyfills/type_traits.hpp"
#include "Strings/StringTraits.hpp"
// Returns the size (in bytes) of an array with n elements.
// Can be very handy to determine the size of a StaticJsonBuffer.
@ -30,23 +26,13 @@ namespace Internals {
class JsonArraySubscript;
}
// An array of JsonVariant.
//
// The constructor is private, instances must be created via
// JsonBuffer::createArray() or JsonBuffer::parseArray().
// A JsonArray can be serialized to a JSON string via JsonArray::printTo().
// It can also be deserialized from a JSON string via JsonBuffer::parseArray().
class JsonArray : public Internals::JsonPrintable<JsonArray>,
public Internals::ReferenceType,
class JsonArray : public Internals::ReferenceType,
public Internals::NonCopyable,
public Internals::List<JsonVariant>,
public Internals::JsonBufferAllocated {
public:
// Create an empty JsonArray attached to the specified JsonBuffer.
// You should not call this constructor directly.
// Instead, use JsonBuffer::createArray() or JsonBuffer::parseArray().
explicit JsonArray(JsonBuffer *buffer) throw()
: Internals::List<JsonVariant>(buffer) {}
explicit JsonArray(Internals::JsonBuffer *buf) throw()
: Internals::List<JsonVariant>(buf) {}
// Gets the value at the specified index
const Internals::JsonArraySubscript operator[](size_t index) const;
@ -99,7 +85,8 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
// bool set(size_t index, TValue value, uint8_t decimals);
// TValue = float, double
template <typename T>
typename Internals::EnableIf<Internals::IsFloatingPoint<T>::value, bool>::type
typename Internals::enable_if<Internals::is_floating_point<T>::value,
bool>::type
set(size_t index, T value, uint8_t decimals) {
return set_impl<const JsonVariant &>(index, JsonVariant(value, decimals));
}
@ -119,11 +106,9 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
}
// Creates a JsonArray and adds a reference at the end of the array.
// It's a shortcut for JsonBuffer::createArray() and JsonArray::add()
JsonArray &createNestedArray();
// Creates a JsonObject and adds a reference at the end of the array.
// It's a shortcut for JsonBuffer::createObject() and JsonArray::add()
JsonObject &createNestedObject();
// Removes element at specified index.
@ -193,12 +178,10 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
}
}
#if ARDUINOJSON_ENABLE_DEPRECATED
DEPRECATED("use remove() instead")
FORCE_INLINE void removeAt(size_t index) {
return remove(index);
template <typename Visitor>
void visit(Visitor &visitor) const {
return visitor.acceptArray(*this);
}
#endif
private:
template <typename TValueRef>

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