Compare commits

..

12 Commits

385 changed files with 8843 additions and 13323 deletions

1
.gitignore vendored
View File

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

View File

@ -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
@ -125,6 +131,4 @@ matrix:
cache:
directories:
- "~/.platformio"
- "fuzzing/json_corpus"
- "fuzzing/msgpack_corpus"
script: scripts/travis/$SCRIPT.sh

View File

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

View File

@ -1,237 +1,30 @@
ArduinoJson: change log
=======================
v6.7.0-beta (2018-12-07)
-----------
HEAD
----
* `JsonObject::createNestedObject()` returns `JsonObject::invalid()` if key is null (issue #1891)
* `JsonObject::createNestedArray()` returns `JsonArray::invalid()` if key is null
v5.13.5
-------
* Fixed warning "unused variable" with GCC 4.4 (issue #912)
* Fixed warning "maybe uninitialized" (issue #909)
* Added an clear message for `StaticJsonDocument`, `DynamicJsonDocument`...
v5.13.4
-------
* Removed the automatic expansion of `DynamicJsonDocument`, it now has a fixed capacity.
* Restored the monotonic allocator because the code was getting too big
* Reduced the memory usage
* Reduced the code size
* Renamed `JsonKey` to `JsonString`
* Removed spurious files in the Particle library
v6.6.0-beta (2018-11-13)
-----------
v5.13.3
-------
* Removed `JsonArray::is<T>(i)` and `JsonArray::set(i,v)`
* Removed `JsonObject::is<T>(k)` and `JsonObject::set(k,v)`
* Replaced `T JsonArray::get<T>(i)` with `JsonVariant JsonArray::get(i)`
* Replaced `T JsonObject::get<T>(k)` with `JsonVariant JsonObject::get(k)`
* Added `JSON_STRING_SIZE()`
* ~~Replacing or removing a value now releases the memory~~
* Added `DeserializationError::code()` to be used in switch statements (issue #846)
v6.5.0-beta (2018-10-13)
-----------
* 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)
v6.4.0-beta (2018-09-11)
-----------
* Copy `JsonArray` and `JsonObject`, instead of storing pointers (issue #780)
* Added `JsonVariant::to<JsonArray>()` and `JsonVariant::to<JsonObject>()`
v6.3.0-beta (2018-08-31)
-----------
* Implemented reference semantics for `JsonVariant`
* Replaced `JsonPair`'s `key` and `value` with `key()` and `value()`
* Fixed `serializeJson(obj[key], dst)` (issue #794)
> ### 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!
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
-------
@ -652,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/).

View File

@ -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)
@ -7,16 +7,10 @@ project(ArduinoJson)
enable_testing()
add_definitions(-DARDUINOJSON_DEBUG)
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
add_compile_options(-g -O0)
endif()
if(${COVERAGE})
set(CMAKE_CXX_FLAGS "-fprofile-arcs -ftest-coverage")
set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
endif()
include_directories(${CMAKE_CURRENT_LIST_DIR}/src)
add_subdirectory(third-party/catch)
add_subdirectory(test)
add_subdirectory(fuzzing)

View File

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

View File

@ -2,7 +2,11 @@
---
[![Build status](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/6.x?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) [![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=6.x)](https://travis-ci.org/bblanchon/ArduinoJson) [![Coverage Status](https://img.shields.io/coveralls/bblanchon/ArduinoJson.svg)](https://coveralls.io/r/bblanchon/ArduinoJson?branch=6.x) [![Star this project](http://githubbadges.com/star.svg?user=bblanchon&repo=ArduinoJson&style=flat&color=fff&background=007ec6)](https://github.com/bblanchon/ArduinoJson)
[![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)
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]}
```

View File

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

View File

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

View File

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

View File

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

View File

@ -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 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);
// 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 ❤❤❤❤❤

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,17 +0,0 @@
# ArduinoJson - arduinojson.org
# Copyright Benoit Blanchon 2014-2018
# MIT License
if(MSVC)
add_compile_options(-D_CRT_SECURE_NO_WARNINGS)
endif()
add_executable(msgpack_fuzzer
msgpack_fuzzer.cpp
fuzzer_main.cpp
)
add_executable(json_fuzzer
json_fuzzer.cpp
fuzzer_main.cpp
)

View File

@ -1,22 +1,19 @@
# CAUTION: this file is invoked by https://github.com/google/oss-fuzz
CXXFLAGS += -I../src -DARDUINOJSON_DEBUG
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
View 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;
}

View File

@ -1,50 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
// This file is NOT use by Google's OSS fuzz
// I only use it to reproduce the bugs found
#include <stdint.h> // size_t
#include <stdio.h> // fopen et al.
#include <stdlib.h> // exit
#include <iostream>
#include <vector>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
std::vector<uint8_t> read(const char* path) {
FILE* f = fopen(path, "rb");
if (!f) {
std::cerr << "Failed to open " << path << std::endl;
exit(1);
}
fseek(f, 0, SEEK_END);
size_t size = ftell(f);
fseek(f, 0, SEEK_SET);
std::vector<uint8_t> buffer(size);
if (fread(buffer.data(), 1, size, f) != size) {
fclose(f);
std::cerr << "Failed to read " << path << std::endl;
exit(1);
}
fclose(f);
return buffer;
}
int main(int argc, const char* argv[]) {
if (argc < 2) {
std::cerr << "Usage: msgpack_fuzzer files" << std::endl;
return 1;
}
for (int i = 1; i < argc; i++) {
std::cout << "Loading " << argv[i] << std::endl;
std::vector<uint8_t> buffer = read(argv[i]);
LLVMFuzzerTestOneInput(buffer.data(), buffer.size());
}
return 0;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1 +0,0 @@


View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

Binary file not shown.

View File

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

Binary file not shown.

Binary file not shown.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,9 +1,9 @@
name=ArduinoJson
version=6.7.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=*

View File

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

View File

@ -1,53 +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
scripts/build-arduino-package.sh
scripts/build-single-header.sh
scripts/wandbox/publish.sh "../ArduinoJson-$TAG.h"

View File

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

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,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 .

View File

@ -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 -timeout=1
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

View File

@ -1,57 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
//
// This example shows how to generate a JSON document with ArduinoJson.
#include <iostream>
#include "ArduinoJson.h"
int main() {
// The JSON document
//
// Inside the brackets, 200 is the RAM allocated to this document.
// Don't forget to change this value to match your requirement.
// Use arduinojson.org/assistant to compute the capacity.
StaticJsonDocument<200> doc;
// StaticJsonObject allocates memory on the stack, it can be
// replaced by DynamicJsonDocument which allocates in the heap.
//
// DynamicJsonDocument doc(200);
// Make our document be an object
JsonObject root = doc.to<JsonObject>();
// Add values in the object
//
// Most of the time, you can rely on the implicit casts.
// In other case, you can do root.set<long>("time", 1351824120);
root["sensor"] = "gps";
root["time"] = 1351824120;
// Add an array.
//
JsonArray data = root.createNestedArray("data");
data.add(48.756080);
data.add(2.302038);
serializeJson(root, std::cout);
// This prints:
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
std::cout << std::endl;
serializeJsonPretty(root, std::cout);
// This prints:
// {
// "sensor": "gps",
// "time": 1351824120,
// "data": [
// 48.756080,
// 2.302038
// ]
// }
return 0;
}

View File

@ -1,59 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
//
// This example shows how to deserialize a JSON document with ArduinoJson.
#include <iostream>
#include "ArduinoJson.h"
int main() {
// Root JSON object
//
// Inside the brackets, 300 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<300> doc;
// StaticJsonDocument<N> allocates memory on the stack, it can be
// replaced by DynamicJsonObject which allocates in the heap.
//
// DynamicJsonObject doc(200);
// JSON 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.
char json[] =
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
// Deserialize the JSON document
DeserializationError error = deserializeJson(doc, json);
// Test if parsing succeeds.
if (error) {
std::cerr << "deserializeJson() failed: " << error.c_str() << std::endl;
return 1;
}
// 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 doc["time"].as<long>();
const char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
double longitude = root["data"][1];
// Print values.
std::cout << sensor << std::endl;
std::cout << time << std::endl;
std::cout << latitude << std::endl;
std::cout << longitude << std::endl;
return 0;
}

View File

@ -1,71 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
//
// This example shows how to generate a JSON document with ArduinoJson.
#include <iostream>
#include "ArduinoJson.h"
int main() {
// Allocate the JSON document
//
// Inside the brackets, 300 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<300> 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) {
std::cerr << "deserializeMsgPack() failed: " << error.c_str() << std::endl;
return 1;
}
// 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 doc["time"].as<long>();
const char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
double longitude = root["data"][1];
// Print values.
std::cout << sensor << std::endl;
std::cout << time << std::endl;
std::cout << latitude << std::endl;
std::cout << longitude << std::endl;
return 0;
}

View File

@ -1,29 +0,0 @@
#!/usr/bin/env bash
set -eu
ARDUINOJSON_H="$1"
read_string() {
jq --slurp --raw-input '.' "$1"
}
compile() {
FILE_PATH="$(dirname $0)/$1.cpp"
cat >parameters.json <<END
{
"code":$(read_string "$FILE_PATH"),
"codes": [{"file":"ArduinoJson.h","code":$(read_string "$ARDUINOJSON_H")}],
"options": "warning",
"compiler": "gcc-4.9.3",
"save": true
}
END
URL=$(curl -sS -H "Content-type: application/json" -d @parameters.json https://wandbox.org/api/compile.json | jq --raw-output .url)
rm parameters.json
echo " $1: $URL"
}
compile "JsonGeneratorExample"
compile "JsonParserExample"
compile "MsgPackParserExample"

View File

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

View File

@ -1,46 +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/Array/ArrayRef.hpp"
#include "ArduinoJson/Object/ObjectRef.hpp"
#include "ArduinoJson/Variant/VariantRef.hpp"
#include "ArduinoJson/DynamicJsonBuffer.hpp"
#include "ArduinoJson/JsonArray.hpp"
#include "ArduinoJson/JsonObject.hpp"
#include "ArduinoJson/StaticJsonBuffer.hpp"
#include "ArduinoJson/Document/DynamicJsonDocument.hpp"
#include "ArduinoJson/Document/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/Array/ArrayImpl.hpp"
#include "ArduinoJson/Array/ArraySubscript.hpp"
#include "ArduinoJson/Collection/CollectionImpl.hpp"
#include "ArduinoJson/Object/ObjectImpl.hpp"
#include "ArduinoJson/Object/ObjectSubscript.hpp"
#include "ArduinoJson/Variant/VariantAsImpl.hpp"
#include "ArduinoJson/Variant/VariantImpl.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 {
typedef ARDUINOJSON_NAMESPACE::ArrayRef JsonArray;
typedef ARDUINOJSON_NAMESPACE::ArrayConstRef JsonArrayConst;
typedef ARDUINOJSON_NAMESPACE::Float JsonFloat;
typedef ARDUINOJSON_NAMESPACE::Integer JsonInteger;
typedef ARDUINOJSON_NAMESPACE::ObjectRef JsonObject;
typedef ARDUINOJSON_NAMESPACE::ObjectConstRef JsonObjectConst;
typedef ARDUINOJSON_NAMESPACE::Pair JsonPair;
typedef ARDUINOJSON_NAMESPACE::UInt JsonUInt;
typedef ARDUINOJSON_NAMESPACE::VariantRef JsonVariant;
typedef ARDUINOJSON_NAMESPACE::VariantConstRef JsonVariantConst;
typedef ARDUINOJSON_NAMESPACE::String JsonString;
using ARDUINOJSON_NAMESPACE::DeserializationError;
using ARDUINOJSON_NAMESPACE::DynamicJsonDocument;
using ARDUINOJSON_NAMESPACE::serialized;
using ARDUINOJSON_NAMESPACE::StaticJsonDocument;
} // namespace ArduinoJson
#include "ArduinoJson/compatibility.hpp"

View File

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

View File

@ -1,19 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Object/ObjectRef.hpp"
#include "ArrayRef.hpp"
namespace ARDUINOJSON_NAMESPACE {
inline ArrayRef ArrayRef::createNestedArray() const {
return add().to<ArrayRef>();
}
inline ObjectRef ArrayRef::createNestedObject() const {
return add().to<ObjectRef>();
}
} // namespace ARDUINOJSON_NAMESPACE

View File

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

View File

@ -1,211 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Variant/VariantData.hpp"
#include "ArrayFunctions.hpp"
#include "ArrayIterator.hpp"
// Returns the size (in bytes) of an array with n elements.
// Can be very handy to determine the size of a StaticMemoryPool.
#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot))
namespace ARDUINOJSON_NAMESPACE {
class ObjectRef;
class ArraySubscript;
template <typename TData>
class ArrayRefBase {
public:
template <typename Visitor>
FORCE_INLINE void accept(Visitor& visitor) const {
arrayAccept(_data, visitor);
}
FORCE_INLINE bool isNull() const {
return _data == 0;
}
FORCE_INLINE VariantConstRef operator[](size_t index) const {
return VariantConstRef(_data ? _data->get(index) : 0);
}
FORCE_INLINE size_t size() const {
return _data ? _data->size() : 0;
}
protected:
ArrayRefBase(TData* data) : _data(data) {}
TData* _data;
};
class ArrayConstRef : public ArrayRefBase<const CollectionData>,
public Visitable {
friend class ArrayRef;
typedef ArrayRefBase<const CollectionData> base_type;
public:
typedef ArrayConstRefIterator iterator;
FORCE_INLINE iterator begin() const {
if (!_data) return iterator();
return iterator(_data->head());
}
FORCE_INLINE iterator end() const {
return iterator();
}
FORCE_INLINE ArrayConstRef() : base_type(0) {}
FORCE_INLINE ArrayConstRef(const CollectionData* data) : base_type(data) {}
FORCE_INLINE bool operator==(ArrayConstRef rhs) const {
return arrayEquals(_data, rhs._data);
}
};
class ArrayRef : public ArrayRefBase<CollectionData>, public Visitable {
typedef ArrayRefBase<CollectionData> base_type;
public:
typedef ArrayIterator iterator;
FORCE_INLINE ArrayRef() : base_type(0), _pool(0) {}
FORCE_INLINE ArrayRef(MemoryPool* pool, CollectionData* data)
: base_type(data), _pool(pool) {}
operator VariantRef() {
return VariantRef(_pool, reinterpret_cast<VariantData*>(_data));
}
operator ArrayConstRef() const {
return ArrayConstRef(_data);
}
// Adds the specified value at the end of the array.
//
// bool add(TValue);
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
// std::string, String, ObjectRef
template <typename T>
FORCE_INLINE bool add(const T& value) const {
return add().set(value);
}
// Adds the specified value at the end of the array.
FORCE_INLINE bool add(ArrayRef value) const {
return add().set(value);
}
//
// bool add(TValue);
// TValue = char*, const char*, const __FlashStringHelper*
template <typename T>
FORCE_INLINE bool add(T* value) const {
return add().set(value);
}
VariantRef add() const {
return VariantRef(_pool, arrayAdd(_data, _pool));
}
FORCE_INLINE iterator begin() const {
if (!_data) return iterator();
return iterator(_pool, _data->head());
}
FORCE_INLINE iterator end() const {
return iterator();
}
// Imports a 1D array
template <typename T, size_t N>
FORCE_INLINE bool copyFrom(T (&array)[N]) const {
return copyFrom(array, N);
}
// Imports a 1D array
template <typename T>
bool copyFrom(T* array, size_t len) const {
bool ok = true;
for (size_t i = 0; i < len; i++) {
ok &= add(array[i]);
}
return ok;
}
// Imports a 2D array
template <typename T, size_t N1, size_t N2>
bool copyFrom(T (&array)[N1][N2]) const {
bool ok = true;
for (size_t i = 0; i < N1; i++) {
ArrayRef nestedArray = createNestedArray();
for (size_t j = 0; j < N2; j++) {
ok &= nestedArray.add(array[i][j]);
}
}
return ok;
}
// Copy a ArrayRef
FORCE_INLINE bool copyFrom(ArrayRef src) const {
if (!_data || !src._data) return false;
return _data->copyFrom(*src._data, _pool);
}
// Exports a 1D array
template <typename T, size_t N>
FORCE_INLINE size_t copyTo(T (&array)[N]) const {
return copyTo(array, N);
}
// Exports a 1D array
template <typename T>
size_t copyTo(T* array, size_t len) const {
size_t i = 0;
for (iterator it = begin(); it != end() && i < len; ++it) array[i++] = *it;
return i;
}
// Exports a 2D array
template <typename T, size_t N1, size_t N2>
void copyTo(T (&array)[N1][N2]) const {
if (!_data) return;
size_t i = 0;
for (iterator it = begin(); it != end() && i < N1; ++it) {
it->as<ArrayRef>().copyTo(array[i++]);
}
}
FORCE_INLINE ArrayRef createNestedArray() const;
FORCE_INLINE ObjectRef createNestedObject() const;
FORCE_INLINE ArraySubscript operator[](size_t index) const;
FORCE_INLINE bool operator==(ArrayRef rhs) const {
return arrayEquals(_data, rhs._data);
}
// Gets the value at the specified index.
FORCE_INLINE VariantRef get(size_t index) const {
return VariantRef(_pool, _data ? _data->get(index) : 0);
}
// Removes element at specified position.
FORCE_INLINE void remove(iterator it) const {
if (!_data) return;
_data->remove(it.internal());
}
// Removes element at specified index.
FORCE_INLINE void remove(size_t index) const {
if (!_data) return;
_data->remove(index);
}
private:
MemoryPool* _pool;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,112 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Configuration.hpp"
#include "../Operators/VariantOperators.hpp"
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4522)
#endif
namespace ARDUINOJSON_NAMESPACE {
class ArraySubscript : public VariantOperators<ArraySubscript>,
public Visitable {
public:
FORCE_INLINE ArraySubscript(ArrayRef array, size_t index)
: _array(array), _index(index) {}
FORCE_INLINE ArraySubscript& operator=(const ArraySubscript& src) {
get_impl().set(src.as<VariantConstRef>());
return *this;
}
// Replaces the value
//
// operator=(const TValue&)
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
// std::string, String, ArrayRef, ObjectRef
template <typename T>
FORCE_INLINE ArraySubscript& operator=(const T& src) {
get_impl().set(src);
return *this;
}
//
// operator=(TValue)
// TValue = char*, const char*, const __FlashStringHelper*
template <typename T>
FORCE_INLINE ArraySubscript& operator=(T* src) {
get_impl().set(src);
return *this;
}
FORCE_INLINE bool isNull() const {
return get_impl().isNull();
}
template <typename T>
FORCE_INLINE typename VariantAs<T>::type as() const {
return get_impl().as<T>();
}
template <typename T>
FORCE_INLINE bool is() const {
return get_impl().is<T>();
}
template <typename T>
FORCE_INLINE typename VariantTo<T>::type to() const {
return get_impl().to<T>();
}
// Replaces the value
//
// bool set(const TValue&)
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
// std::string, String, ArrayRef, ObjectRef
template <typename TValue>
FORCE_INLINE bool set(const TValue& value) const {
return get_impl().set(value);
}
//
// bool set(TValue)
// TValue = char*, const char*, const __FlashStringHelper*
template <typename TValue>
FORCE_INLINE bool set(TValue* value) const {
return get_impl().set(value);
}
template <typename Visitor>
void accept(Visitor& visitor) const {
return get_impl().accept(visitor);
}
FORCE_INLINE size_t size() const {
return get_impl().size();
}
private:
FORCE_INLINE VariantRef get_impl() const {
return _array.get(_index);
}
ArrayRef _array;
const size_t _index;
};
template <typename TImpl>
inline ArraySubscript VariantSubscripts<TImpl>::operator[](size_t index) const {
return impl()->template as<ArrayRef>()[index];
}
inline ArraySubscript ArrayRef::operator[](size_t index) const {
return ArraySubscript(*this, index);
}
} // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER
#pragma warning(pop)
#endif

View File

@ -1,68 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
class MemoryPool;
class VariantData;
class VariantSlot;
class CollectionData {
VariantSlot *_head;
VariantSlot *_tail;
public:
// Must be a POD!
// - no constructor
// - no destructor
// - no virtual
// - no inheritance
VariantSlot *addSlot(MemoryPool *);
VariantData *add(MemoryPool *pool);
template <typename TKey>
VariantData *add(TKey key, MemoryPool *pool);
void clear();
template <typename TKey>
bool containsKey(const TKey &key) const;
bool copyFrom(const CollectionData &src, MemoryPool *pool);
bool equalsArray(const CollectionData &other) const;
bool equalsObject(const CollectionData &other) const;
VariantData *get(size_t index) const;
template <typename TKey>
VariantData *get(TKey key) const;
VariantSlot *head() const {
return _head;
}
void remove(size_t index);
template <typename TKey>
void remove(TKey key) {
remove(getSlot(key));
}
void remove(VariantSlot *slot);
size_t size() const;
private:
VariantSlot *getSlot(size_t index) const;
template <typename TKey>
VariantSlot *getSlot(TKey key) const;
VariantSlot *getPreviousSlot(VariantSlot *) const;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,145 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Variant/VariantData.hpp"
#include "CollectionData.hpp"
namespace ARDUINOJSON_NAMESPACE {
inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) {
VariantSlot* slot = pool->allocVariant();
if (!slot) return 0;
if (_tail) {
_tail->setNextNotNull(slot);
_tail = slot;
} else {
_head = slot;
_tail = slot;
}
slot->clear();
return slot;
}
inline VariantData* CollectionData::add(MemoryPool* pool) {
return addSlot(pool)->data();
}
template <typename TKey>
inline VariantData* CollectionData::add(TKey key, MemoryPool* pool) {
VariantSlot* slot = addSlot(pool);
if (!slotSetKey(slot, key, pool)) return 0;
return slot->data();
}
inline void CollectionData::clear() {
_head = 0;
_tail = 0;
}
template <typename TKey>
inline bool CollectionData::containsKey(const TKey& key) const {
return getSlot(key) != 0;
}
inline bool CollectionData::copyFrom(const CollectionData& src,
MemoryPool* pool) {
clear();
for (VariantSlot* s = src._head; s; s = s->next()) {
VariantData* var;
if (s->key() != 0) {
if (s->ownsKey())
var = add(RamStringWrapper(s->key()), pool);
else
var = add(ConstRamStringWrapper(s->key()), pool);
} else {
var = add(pool);
}
if (!var) return false;
if (!var->copyFrom(*s->data(), pool)) return false;
}
return true;
}
inline bool CollectionData::equalsObject(const CollectionData& other) const {
size_t count = 0;
for (VariantSlot* slot = _head; slot; slot = slot->next()) {
VariantData* v1 = slot->data();
VariantData* v2 = other.get(wrapString(slot->key()));
if (!variantEquals(v1, v2)) return false;
count++;
}
return count == other.size();
}
inline bool CollectionData::equalsArray(const CollectionData& other) const {
VariantSlot* s1 = _head;
VariantSlot* s2 = other._head;
for (;;) {
if (s1 == s2) return true;
if (!s1 || !s2) return false;
if (!variantEquals(s1->data(), s2->data())) return false;
s1 = s1->next();
s2 = s2->next();
}
}
template <typename TKey>
inline VariantSlot* CollectionData::getSlot(TKey key) const {
VariantSlot* slot = _head;
while (slot) {
if (key.equals(slot->key())) break;
slot = slot->next();
}
return slot;
}
inline VariantSlot* CollectionData::getSlot(size_t index) const {
return _head->next(index);
}
inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const {
VariantSlot* current = _head;
while (current) {
VariantSlot* next = current->next();
if (next == target) return current;
current = next;
}
return 0;
}
template <typename TKey>
inline VariantData* CollectionData::get(TKey key) const {
VariantSlot* slot = getSlot(key);
return slot ? slot->data() : 0;
}
inline VariantData* CollectionData::get(size_t index) const {
VariantSlot* slot = getSlot(index);
return slot ? slot->data() : 0;
}
inline void CollectionData::remove(VariantSlot* slot) {
if (!slot) return;
VariantSlot* prev = getPreviousSlot(slot);
VariantSlot* next = slot->next();
if (prev)
prev->setNext(next);
else
_head = next;
if (!next) _tail = prev;
}
inline void CollectionData::remove(size_t index) {
remove(getSlot(index));
}
inline size_t CollectionData::size() const {
return slotSize(_head);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -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
@ -130,6 +120,21 @@
#endif
#endif
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
#ifdef ARDUINO_ARCH_AVR
// alignment isn't needed for 8-bit AVR
#define ARDUINOJSON_ENABLE_ALIGNMENT 0
#else
// but most processors need pointers to be align on word size
#define ARDUINOJSON_ENABLE_ALIGNMENT 1
#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
@ -141,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

View File

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

View 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

View File

@ -0,0 +1,18 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../Configuration.hpp"
namespace ArduinoJson {
namespace Internals {
#if ARDUINOJSON_USE_DOUBLE
typedef double JsonFloat;
#else
typedef float JsonFloat;
#endif
} // namespace Internals
} // namespace ArduinoJson

View File

@ -0,0 +1,23 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../Configuration.hpp"
namespace ArduinoJson {
namespace Internals {
#if ARDUINOJSON_USE_LONG_LONG
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 Internals
} // namespace ArduinoJson

View File

@ -0,0 +1,42 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
namespace ArduinoJson {
namespace Internals {
// A metafunction that returns the type of the value returned by
// JsonVariant::as<T>()
template <typename T>
struct JsonVariantAs {
typedef T type;
};
template <>
struct JsonVariantAs<char*> {
typedef const char* type;
};
template <>
struct JsonVariantAs<JsonArray> {
typedef JsonArray& type;
};
template <>
struct JsonVariantAs<const JsonArray> {
typedef const JsonArray& type;
};
template <>
struct JsonVariantAs<JsonObject> {
typedef JsonObject& type;
};
template <>
struct JsonVariantAs<const JsonObject> {
typedef const JsonObject& type;
};
} // namespace Internals
} // namespace ArduinoJson

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View File

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

View File

@ -1,59 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
class UnsafeCharPointerReader {
const char* _ptr;
public:
explicit UnsafeCharPointerReader(const char* ptr)
: _ptr(ptr ? ptr : reinterpret_cast<const char*>("")) {}
char read() {
return static_cast<char>(*_ptr++);
}
bool ended() const {
// we cannot know, that's why it's unsafe
return false;
}
};
class SafeCharPointerReader {
const char* _ptr;
const char* _end;
public:
explicit SafeCharPointerReader(const char* ptr, size_t len)
: _ptr(ptr ? ptr : reinterpret_cast<const char*>("")), _end(_ptr + len) {}
char read() {
return static_cast<char>(*_ptr++);
}
bool ended() const {
return _ptr == _end;
}
};
template <typename TChar>
inline UnsafeCharPointerReader makeReader(TChar* input) {
return UnsafeCharPointerReader(reinterpret_cast<const char*>(input));
}
template <typename TChar>
inline SafeCharPointerReader makeReader(TChar* input, size_t n) {
return SafeCharPointerReader(reinterpret_cast<const char*>(input), n);
}
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
inline SafeCharPointerReader makeReader(const ::String& input) {
return SafeCharPointerReader(input.c_str(), input.length());
}
#endif
} // namespace ARDUINOJSON_NAMESPACE

View 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

View File

@ -1,113 +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 {
// safe bool idiom
typedef void (DeserializationError::*bool_type)() const;
void safeBoolHelper() const {}
public:
enum Code {
Ok,
IncompleteInput,
InvalidInput,
NoMemory,
NotSupported,
TooDeep
};
DeserializationError() {}
DeserializationError(Code c) : _code(c) {}
// Compare with DeserializationError
friend bool operator==(const DeserializationError& lhs,
const DeserializationError& rhs) {
return lhs._code == rhs._code;
}
friend bool operator!=(const DeserializationError& lhs,
const DeserializationError& rhs) {
return lhs._code != rhs._code;
}
// Compare with Code
friend bool operator==(const DeserializationError& lhs, Code rhs) {
return lhs._code == rhs;
}
friend bool operator==(Code lhs, const DeserializationError& rhs) {
return lhs == rhs._code;
}
friend bool operator!=(const DeserializationError& lhs, Code rhs) {
return lhs._code != rhs;
}
friend bool operator!=(Code lhs, const DeserializationError& rhs) {
return lhs != rhs._code;
}
// Behaves like a bool
operator bool_type() const {
return _code != Ok ? &DeserializationError::safeBoolHelper : 0;
}
friend bool operator==(bool value, const DeserializationError& err) {
return static_cast<bool>(err) == value;
}
friend bool operator==(const DeserializationError& err, bool value) {
return static_cast<bool>(err) == value;
}
friend bool operator!=(bool value, const DeserializationError& err) {
return static_cast<bool>(err) != value;
}
friend bool operator!=(const DeserializationError& err, bool value) {
return static_cast<bool>(err) != value;
}
// Returns internal enum, useful for switch statement
Code code() const {
return _code;
}
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

View File

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

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