Compare commits

..

63 Commits

Author SHA1 Message Date
9f1421e0a6 Set version to 6.5.0-beta 2018-10-13 13:23:34 +02:00
84f199f0dd Added copy-constructor and copy-assignment-operator for JsonDocument (issue #827) 2018-10-13 13:21:30 +02:00
8230f8fc9b Restored JsonVariantLocal to fix the use-after-free 2018-10-12 20:00:49 +01:00
02d809f3f4 Added Visitable to reduce the number of definitions of operator<< 2018-10-12 17:59:50 +02:00
b0560cbd99 Added JsonArrayConst, JsonObjectConst, and JsonVariantConst 2018-10-12 12:00:27 +02:00
d1003ff6c9 Simplified string handling in JsonObject 2018-10-10 09:18:36 +02:00
b11ad4077b Merge branch 'master' into 6.x 2018-10-09 15:00:49 +02:00
5dc7dc1216 Increased the default capacity of DynamicJsonDocument 2018-10-08 18:32:58 +02:00
39e5660c4a Extracted a base class for JsonDocument 2018-10-04 14:59:07 +02:00
6b985b2d1f Fixed object keys not being duplicated 2018-10-04 11:16:23 +02:00
527dc19794 Allow mixed configuration in compilation units (issue #809) 2018-10-02 16:54:05 +02:00
29e71cbb16 Added implicit conversion from JsonArray and JsonObject to JsonVariant 2018-10-01 12:55:40 +02:00
2d54019f83 Set version to 6.4.0-beta 2018-09-11 16:31:04 +02:00
98c8e8e35a Added a test for issue #808 2018-09-11 16:21:30 +02:00
b106b1ed14 Copy JsonArray and JsonObject, instead of storing pointers (fixes #780) 2018-09-11 16:06:08 +02:00
2998a55f0b Renamed JsonBuffer to MemoryPool 2018-09-03 16:14:21 +02:00
e5c4778ff7 Updated publish script 2018-08-31 17:04:22 +02:00
2ec9569b36 Set version to 6.3.0-beta 2018-08-31 16:57:14 +02:00
58303d0837 Added date in change log 2018-08-31 16:38:42 +02:00
e3639918eb Reduced executable size 2018-08-31 16:29:08 +02:00
6d290bd001 Fixed duplication of char* 2018-08-22 14:37:17 +02:00
7683667b3c Fixed serializeJson(obj[key], dst) (closes #794) 2018-08-21 18:07:41 +02:00
9cbc891816 Implemented reference semantics for JsonVariant 2018-08-21 17:56:16 +02:00
0454bd1ef6 Set version to 6.2.3-beta 2018-07-19 18:28:03 +02:00
f139100b23 Added a script to update the version number 2018-07-19 18:27:44 +02:00
3f666bd5f0 Fixed exception when using Flash strings as object keys (fixes #784) 2018-07-19 17:22:28 +02:00
d53a93e0ae Set version to 6.2.2-beta 2018-07-18 20:21:00 +02:00
2059d610a8 Fixed invalid application of 'sizeof' to incomplete type (closes #783) 2018-07-18 20:19:22 +02:00
9bbfbd0a6a Set version to 6.2.1-beta 2018-07-17 10:27:04 +02:00
6e4f1dc756 Fixed JsonObject not inserting keys of type String (fixes #782) 2018-07-17 10:24:21 +02:00
dc13882624 Update badges to show status of branch 6.x 2018-07-12 11:01:26 +02:00
6bb17d5896 Checked that issue issue #628 is fixed 2018-07-12 10:33:56 +02:00
1a513cbd16 Set version to 6.2.0-beta 2018-07-12 09:10:13 +02:00
87fa87d87b Renamed function RawJson() to serialized() 2018-07-12 09:08:20 +02:00
765752261c Improved float serialization when -fsingle-precision-constant is used 2018-07-04 12:07:03 +02:00
037f90aada Disabled lazy number deserialization (fixes #772) 2018-07-04 12:02:58 +02:00
1397bec066 Set version to 6.1.0-beta 2018-07-02 09:54:35 +02:00
b105e6f7c4 Return JsonArray and JsonObject by value (closes #309) 2018-07-02 09:35:21 +02:00
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
357 changed files with 12023 additions and 7607 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:
@ -119,7 +113,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: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,216 @@
ArduinoJson: change log
=======================
HEAD
----
v6.5.0-beta (2018-10-13)
-----------
* `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 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
* 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);
> ```
v5.13.2
-------
@ -445,51 +631,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/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)
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);
JsonObjectRef root = doc.as<JsonObject>();
const char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
@ -80,17 +77,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++
StaticJsonBuffer<200> jsonBuffer;
DynamicJsonDocument doc;
JsonObject& root = jsonBuffer.createObject();
JsonObject root = doc.to<JsonObject>();
root["sensor"] = "gps";
root["time"] = 1351824120;
JsonArray& data = root.createNestedArray("data");
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.4.0.{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"));
}
@ -130,15 +132,4 @@ void loop() {
// not used in this example
}
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// serialization or deserialization problem.
//
// The book "Mastering ArduinoJson" contains a case study of a project that has
// a complex configuration with nested members.
// Contrary to this example, the project in the book uses the SPIFFS filesystem.
// Learn more at https://arduinojson.org/book/
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
// Visit https://arduinojson.org/v6/example/config/ for more.

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");
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",
@ -67,15 +61,4 @@ void loop() {
// not used in this example
}
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// serialization problem.
//
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
// It begins with a simple example, like the one above, and then adds more
// features like serializing directly to a file or an HTTP request.
// Learn more at https://arduinojson.org/book/
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
// Visit https://arduinojson.org/v6/example/generator/ for more.

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*>());
@ -97,16 +99,4 @@ void loop() {
// not used in this example
}
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// serialization problem.
//
// The book "Mastering ArduinoJson" contains a tutorial on deserialization
// showing how to parse the response from 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 ❤❤❤❤❤
// Visit https://arduinojson.org/v6/example/http-client/ for more.

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.
@ -64,15 +64,4 @@ void loop() {
// not used in this example
}
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// deserialization problem.
//
// The book "Mastering ArduinoJson" contains a tutorial on deserialization.
// It begins with a simple example, like the one above, and then adds more
// features like deserializing directly from a file or an HTTP request.
// Learn more at https://arduinojson.org/book/
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
// Visit https://arduinojson.org/v6/example/parser/ for more.

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,15 +51,15 @@ 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");
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: "));
root.printTo(Serial);
serializeJson(root, Serial);
Serial.println();
// Write response headers
@ -89,21 +89,10 @@ void loop() {
client.println();
// Write JSON document
root.prettyPrintTo(client);
serializeJsonPretty(root, client);
// Disconnect
client.stop();
}
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// serialization problem.
//
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
// It begins with a simple example, then adds more features like serializing
// directly to a file or an HTTP client.
// Learn more at https://arduinojson.org/book/
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
// Visit https://arduinojson.org/v6/example/http-server/ for more.

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,15 +43,15 @@ 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");
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);
root.printTo(Serial);
serializeJson(root, Serial);
// Send UDP packet
udp.beginPacket(remoteIp, remotePort);
root.printTo(udp);
serializeJson(root, udp);
udp.println();
udp.endPacket();
@ -87,15 +87,4 @@ void loop() {
delay(10000);
}
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any
// serialization problem.
//
// The book "Mastering ArduinoJson" contains a tutorial on serialization.
// It begins with a simple example, then adds more features like serializing
// directly to a file or any stream.
// Learn more at https://arduinojson.org/book/
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
// Visit https://arduinojson.org/v6/example/udp-beacon/ for more.

View File

@ -0,0 +1,80 @@
// 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-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
//
// This example shows the different ways you can use Flash strings with
@ -14,34 +14,35 @@
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\""));
// It works with serialized() too:
obj["sensor"] = serialized(F("\"gps\""));
obj["sensor"] = serialized(F("\xA3gps"), 3);
// You can compare the content of a JsonVariant to a Flash String
if (root["sensor"] == F("gps")) {
if (obj["sensor"] == F("gps")) {
// ...
}
@ -56,15 +57,4 @@ void loop() {
// not used in this example
}
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any memory
// problem.
//
// The book "Mastering ArduinoJson" contains a quick C++ course that explains
// how your microcontroller stores strings in memory. It also tells why you
// should not abuse Flash strings with ArduinoJson.
// Learn more at https://arduinojson.org/book/
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
// Visit https://arduinojson.org/v6/example/progmem/ for more.

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,64 +11,55 @@
#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);
// It works with serialized() too:
obj["sensor"] = serialized(sensor);
// You can also concatenate strings
// WARNING: the content of the String will be duplicated in the 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() {
// not used in this example
}
// See also
// --------
//
// https://arduinojson.org/ contains the documentation for all the functions
// used above. It also includes an FAQ that will help you solve any problem.
//
// The book "Mastering ArduinoJson" contains a quick C++ course that explains
// how your microcontroller stores strings in memory. On several occasions, it
// shows how you can avoid String in your program.
// Learn more at https://arduinojson.org/book/
// Use the coupon code TWENTY for a 20% discount ❤❤❤❤❤
// Visit https://arduinojson.org/v6/example/string/ for more.

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.5.0-beta",
"authors": {
"name": "Benoit Blanchon",
"url": "https://blog.benoitblanchon.fr"

View File

@ -1,9 +1,9 @@
name=ArduinoJson
version=5.13.5
version=6.5.0-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

49
scripts/publish.sh Normal file
View File

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

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,43 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "ArduinoJson/version.hpp"
#include "ArduinoJson/Namespace.hpp"
#include "ArduinoJson/DynamicJsonBuffer.hpp"
#include "ArduinoJson/JsonArray.hpp"
#include "ArduinoJson/JsonDocument.hpp"
#include "ArduinoJson/JsonObject.hpp"
#include "ArduinoJson/StaticJsonBuffer.hpp"
#include "ArduinoJson/JsonVariant.hpp"
#include "ArduinoJson/Deserialization/JsonParserImpl.hpp"
#include "ArduinoJson/Data/VariantAsImpl.hpp"
#include "ArduinoJson/JsonArrayImpl.hpp"
#include "ArduinoJson/JsonBufferImpl.hpp"
#include "ArduinoJson/JsonArraySubscript.hpp"
#include "ArduinoJson/JsonObjectImpl.hpp"
#include "ArduinoJson/JsonObjectSubscript.hpp"
#include "ArduinoJson/JsonVariantImpl.hpp"
#include "ArduinoJson/Serialization/JsonSerializerImpl.hpp"
#include "ArduinoJson/compatibility.hpp"
#include "ArduinoJson/Json/JsonDeserializer.hpp"
#include "ArduinoJson/Json/JsonSerializer.hpp"
#include "ArduinoJson/Json/PrettyJsonSerializer.hpp"
#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp"
namespace ArduinoJson {
using ARDUINOJSON_NAMESPACE::DeserializationError;
using ARDUINOJSON_NAMESPACE::DynamicJsonDocument;
using ARDUINOJSON_NAMESPACE::JsonArray;
using ARDUINOJSON_NAMESPACE::JsonArrayConst;
using ARDUINOJSON_NAMESPACE::JsonFloat;
using ARDUINOJSON_NAMESPACE::JsonInteger;
using ARDUINOJSON_NAMESPACE::JsonKey;
using ARDUINOJSON_NAMESPACE::JsonObject;
using ARDUINOJSON_NAMESPACE::JsonObjectConst;
using ARDUINOJSON_NAMESPACE::JsonPair;
using ARDUINOJSON_NAMESPACE::JsonUInt;
using ARDUINOJSON_NAMESPACE::JsonVariant;
using ARDUINOJSON_NAMESPACE::JsonVariantConst;
using ARDUINOJSON_NAMESPACE::serialized;
using ARDUINOJSON_NAMESPACE::StaticJsonDocument;
} // namespace ArduinoJson

View File

@ -1,9 +1,21 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// 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) || \
@ -25,9 +37,6 @@
#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
@ -44,6 +53,11 @@
#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
@ -53,22 +67,13 @@
// Use long long when available
#ifndef ARDUINOJSON_USE_LONG_LONG
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)
#if ARDUINOJSON_HAS_LONG_LONG || ARDUINOJSON_HAS_INT64
#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
@ -84,6 +89,11 @@
#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,11 +140,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
@ -146,6 +151,12 @@
#define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5
#endif
#if ARDUINOJSON_USE_LONG_LONG && ARDUINOJSON_USE_INT64
#error ARDUINOJSON_USE_LONG_LONG and ARDUINOJSON_USE_INT64 cannot be set together
#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

@ -0,0 +1,99 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonVariantData.hpp"
#include "Slot.hpp"
#include "SlotFunctions.hpp"
namespace ARDUINOJSON_NAMESPACE {
inline JsonVariantData* arrayAdd(JsonArrayData* arr, MemoryPool* pool) {
if (!arr) return 0;
Slot* slot = new (pool) Slot();
if (!slot) return 0;
slot->next = 0;
if (arr->tail) {
slot->prev = arr->tail;
arr->tail->next = slot;
arr->tail = slot;
} else {
slot->prev = 0;
arr->head = slot;
arr->tail = slot;
}
return &slot->value;
}
inline Slot* arrayGetSlot(const JsonArrayData* arr, size_t index) {
if (!arr) return 0;
return slotAdvance(arr->head, index);
}
inline JsonVariantData* arrayGet(const JsonArrayData* arr, size_t index) {
Slot* slot = arrayGetSlot(arr, index);
return slot ? &slot->value : 0;
}
inline void arrayRemove(JsonArrayData* arr, Slot* slot) {
if (!arr || !slot) return;
if (slot->prev)
slot->prev->next = slot->next;
else
arr->head = slot->next;
if (slot->next)
slot->next->prev = slot->prev;
else
arr->tail = slot->prev;
}
inline void arrayRemove(JsonArrayData* arr, size_t index) {
arrayRemove(arr, arrayGetSlot(arr, index));
}
inline void arrayClear(JsonArrayData* arr) {
if (!arr) return;
arr->head = 0;
arr->tail = 0;
}
bool variantCopy(JsonVariantData*, const JsonVariantData*, MemoryPool*);
inline bool arrayCopy(JsonArrayData* dst, const JsonArrayData* src,
MemoryPool* pool) {
if (!dst || !src) return false;
arrayClear(dst);
for (Slot* s = src->head; s; s = s->next) {
if (!variantCopy(arrayAdd(dst, pool), &s->value, pool)) return false;
}
return true;
}
bool variantEquals(const JsonVariantData*, const JsonVariantData*);
inline bool arrayEquals(const JsonArrayData* a1, const JsonArrayData* a2) {
if (a1 == a2) return true;
if (!a1 || !a2) return false;
Slot* s1 = a1->head;
Slot* s2 = a2->head;
for (;;) {
if (s1 == s2) return true;
if (!s1 || !s2) return false;
if (!variantEquals(&s1->value, &s2->value)) return false;
s1 = s1->next;
s2 = s2->next;
}
}
inline size_t arraySize(const JsonArrayData* arr) {
if (!arr) return 0;
return slotSize(arr->head);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

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

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

View File

@ -1,23 +1,20 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Configuration.hpp"
namespace ArduinoJson {
namespace Internals {
#include <stdint.h> // int64_t
namespace ARDUINOJSON_NAMESPACE {
#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;
typedef int64_t JsonInteger;
typedef uint64_t JsonUInt;
#else
typedef long JsonInteger;
typedef unsigned long JsonUInt;
#endif
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,11 +1,17 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
class JsonArray;
class JsonArrayConst;
class JsonObject;
class JsonObjectConst;
class JsonVariant;
class JsonVariantConst;
// A metafunction that returns the type of the value returned by
// JsonVariant::as<T>()
@ -19,24 +25,25 @@ struct JsonVariantAs<char*> {
typedef const char* type;
};
template <>
struct JsonVariantAs<JsonArray> {
typedef JsonArray& type;
// A metafunction that returns the type of the value returned by
// JsonVariant::as<T>()
template <typename T>
struct JsonVariantConstAs {
typedef typename JsonVariantAs<T>::type type;
};
template <>
struct JsonVariantAs<const JsonArray> {
typedef const JsonArray& type;
struct JsonVariantConstAs<JsonVariant> {
typedef JsonVariantConst type;
};
template <>
struct JsonVariantAs<JsonObject> {
typedef JsonObject& type;
struct JsonVariantConstAs<JsonObject> {
typedef JsonObjectConst type;
};
template <>
struct JsonVariantAs<const JsonObject> {
typedef const JsonObject& type;
struct JsonVariantConstAs<JsonArray> {
typedef JsonArrayConst type;
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,27 +0,0 @@
// 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,79 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include <stddef.h> // ptrdiff_t, size_t
#include "JsonFloat.hpp"
#include "JsonInteger.hpp"
namespace ARDUINOJSON_NAMESPACE {
enum JsonVariantType {
JSON_NULL,
JSON_LINKED_RAW,
JSON_OWNED_RAW,
JSON_LINKED_STRING,
JSON_OWNED_STRING,
JSON_BOOLEAN,
JSON_POSITIVE_INTEGER,
JSON_NEGATIVE_INTEGER,
JSON_ARRAY,
JSON_OBJECT,
JSON_FLOAT
};
struct JsonObjectData {
struct Slot *head;
struct Slot *tail;
};
struct JsonArrayData {
struct Slot *head;
struct Slot *tail;
};
struct RawData {
const char *data;
size_t size;
};
// A union that defines the actual content of a JsonVariantData.
// The enum JsonVariantType determines which member is in use.
union JsonVariantContent {
JsonFloat asFloat;
JsonUInt asInteger;
JsonArrayData asArray;
JsonObjectData asObject;
const char *asString;
struct {
const char *data;
size_t size;
} asRaw;
};
// this struct must be a POD type to prevent error calling offsetof on clang
struct JsonVariantData {
bool keyIsStatic : 1;
JsonVariantType type : 7;
JsonVariantContent content;
};
inline JsonVariantData *getVariantData(JsonArrayData *arr) {
const ptrdiff_t offset = offsetof(JsonVariantData, content) -
offsetof(JsonVariantContent, asArray);
if (!arr) return 0;
return reinterpret_cast<JsonVariantData *>(reinterpret_cast<char *>(arr) -
offset);
}
inline JsonVariantData *getVariantData(JsonObjectData *obj) {
const ptrdiff_t offset = offsetof(JsonVariantData, content) -
offsetof(JsonVariantContent, asObject);
if (!obj) return 0;
return reinterpret_cast<JsonVariantData *>(reinterpret_cast<char *>(obj) -
offset);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,23 +0,0 @@
// 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,30 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
class JsonArray;
class JsonObject;
class JsonVariant;
// A metafunction that returns the type of the value returned by
// JsonVariant::to<T>()
template <typename T>
struct JsonVariantTo {};
template <>
struct JsonVariantTo<JsonArray> {
typedef JsonArray type;
};
template <>
struct JsonVariantTo<JsonObject> {
typedef JsonObject type;
};
template <>
struct JsonVariantTo<JsonVariant> {
typedef JsonVariant type;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

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

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

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

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

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

@ -1,23 +0,0 @@
// 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,123 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonVariantData.hpp"
#include "SlotFunctions.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TKey>
inline Slot* objectFindSlot(const JsonObjectData* obj, TKey key) {
if (!obj) return 0;
Slot* slot = obj->head;
while (slot) {
if (key.equals(slot->key)) break;
slot = slot->next;
}
return slot;
}
template <typename TKey>
inline bool objectContainsKey(const JsonObjectData* obj, const TKey& key) {
return objectFindSlot(obj, key) != 0;
}
template <typename TKey>
inline JsonVariantData* objectAdd(JsonObjectData* obj, TKey key,
MemoryPool* pool) {
Slot* slot = new (pool) Slot();
if (!slot) return 0;
slot->next = 0;
if (obj->tail) {
slot->prev = obj->tail;
obj->tail->next = slot;
obj->tail = slot;
} else {
slot->prev = 0;
obj->head = slot;
obj->tail = slot;
}
if (!slotSetKey(slot, key, pool)) return 0;
return &slot->value;
}
template <typename TKey>
inline JsonVariantData* objectSet(JsonObjectData* obj, TKey key,
MemoryPool* pool) {
if (!obj) return 0;
// ignore null key
if (key.isNull()) return 0;
// search a matching key
Slot* slot = objectFindSlot(obj, key);
if (slot) return &slot->value;
return objectAdd(obj, key, pool);
}
template <typename TKey>
inline JsonVariantData* objectGet(const JsonObjectData* obj, TKey key) {
Slot* slot = objectFindSlot(obj, key);
return slot ? &slot->value : 0;
}
inline void objectClear(JsonObjectData* obj) {
if (!obj) return;
obj->head = 0;
obj->tail = 0;
}
inline void objectRemove(JsonObjectData* obj, Slot* slot) {
if (!obj) return;
if (!slot) return;
if (slot->prev)
slot->prev->next = slot->next;
else
obj->head = slot->next;
if (slot->next)
slot->next->prev = slot->prev;
else
obj->tail = slot->prev;
}
inline size_t objectSize(const JsonObjectData* obj) {
if (!obj) return 0;
return slotSize(obj->head);
}
// bool variantCopy(JsonVariantData*, const JsonVariantData*, MemoryPool*);
inline bool objectCopy(JsonObjectData* dst, const JsonObjectData* src,
MemoryPool* pool) {
if (!dst || !src) return false;
objectClear(dst);
for (Slot* s = src->head; s; s = s->next) {
JsonVariantData* var;
if (s->value.keyIsStatic)
var = objectAdd(dst, ZeroTerminatedRamStringConst(s->key), pool);
else
var = objectAdd(dst, ZeroTerminatedRamString(s->key), pool);
if (!variantCopy(var, &s->value, pool)) return false;
}
return true;
}
inline bool objectEquals(const JsonObjectData* o1, const JsonObjectData* o2) {
if (o1 == o2) return true;
if (!o1 || !o2) return false;
for (Slot* s = o1->head; s; s = s->next) {
JsonVariantData* v1 = &s->value;
JsonVariantData* v2 = objectGet(o2, makeString(s->key));
if (!variantEquals(v1, v2)) return false;
}
return true;
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,24 +0,0 @@
// 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,19 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Memory/AllocableInMemoryPool.hpp"
#include "JsonVariantData.hpp"
namespace ARDUINOJSON_NAMESPACE {
struct Slot : AllocableInMemoryPool {
JsonVariantData value;
struct Slot* next;
struct Slot* prev;
const char* key;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,59 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Strings/StringTypes.hpp"
#include "JsonVariantData.hpp"
#include "Slot.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TKey>
inline bool slotSetKey(Slot* slot, TKey key, MemoryPool* pool) {
const char* dup = key.save(pool);
if (!dup) return false;
slot->key = dup;
slot->value.keyIsStatic = false;
return true;
}
inline bool slotSetKey(Slot* slot, ZeroTerminatedRamStringConst key,
MemoryPool* pool) {
slot->key = key.save(pool);
slot->value.keyIsStatic = true;
return true;
}
inline bool slotSetKey(Slot* slot, StringInMemoryPool key, MemoryPool* pool) {
slot->key = key.save(pool);
slot->value.keyIsStatic = false;
return true;
}
inline const Slot* slotAdvance(const Slot* slot, size_t distance) {
while (distance && slot) {
slot = slot->next;
distance--;
}
return slot;
}
inline Slot* slotAdvance(Slot* slot, size_t distance) {
while (distance && slot) {
slot = slot->next;
distance--;
}
return slot;
}
inline size_t slotSize(const Slot* slot) {
size_t n = 0;
while (slot) {
n++;
slot = slot->next;
}
return n;
}
} // namespace ARDUINOJSON_NAMESPACE

View File

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

@ -0,0 +1,48 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Serialization/DynamicStringWriter.hpp"
#include "VariantFunctions.hpp"
namespace ARDUINOJSON_NAMESPACE {
class JsonVariantConst;
template <typename T>
inline typename enable_if<is_integral<T>::value, T>::type variantAs(
const JsonVariantData* _data) {
return variantAsIntegral<T>(_data);
}
template <typename T>
inline typename enable_if<is_same<T, bool>::value, T>::type variantAs(
const JsonVariantData* _data) {
return variantAsBoolean(_data);
}
template <typename T>
inline typename enable_if<is_floating_point<T>::value, T>::type variantAs(
const JsonVariantData* _data) {
return variantAsFloat<T>(_data);
}
template <typename T>
inline typename enable_if<is_same<T, const char*>::value ||
is_same<T, char*>::value,
const char*>::type
variantAs(const JsonVariantData* _data) {
return variantAsString(_data);
}
template <typename T>
inline typename enable_if<is_same<JsonVariantConst, T>::value, T>::type
variantAs(const JsonVariantData* _data);
template <typename T>
inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs(
const JsonVariantData* _data);
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,29 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../JsonVariant.hpp"
#include "../Serialization/DynamicStringWriter.hpp"
#include "VariantFunctions.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename T>
inline typename enable_if<is_same<JsonVariantConst, T>::value, T>::type
variantAs(const JsonVariantData* _data) {
return JsonVariantConst(_data);
}
template <typename T>
inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs(
const JsonVariantData* _data) {
const char* cstr = variantAsString(_data);
if (cstr) return T(cstr);
T s;
serializeJson(JsonVariantConst(_data), s);
return s;
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,287 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Numbers/parseFloat.hpp"
#include "../Numbers/parseInteger.hpp"
#include "../SerializedValue.hpp"
#include "ArrayFunctions.hpp"
#include "JsonVariantData.hpp"
#include "ObjectFunctions.hpp"
#include "Slot.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename T>
inline T variantAsIntegral(const JsonVariantData* var) {
if (!var) return 0;
switch (var->type) {
case JSON_POSITIVE_INTEGER:
case JSON_BOOLEAN:
return T(var->content.asInteger);
case JSON_NEGATIVE_INTEGER:
return T(~var->content.asInteger + 1);
case JSON_LINKED_STRING:
case JSON_OWNED_STRING:
return parseInteger<T>(var->content.asString);
case JSON_FLOAT:
return T(var->content.asFloat);
default:
return 0;
}
}
inline bool variantAsBoolean(const JsonVariantData* var) {
return variantAsIntegral<int>(var) != 0;
}
// T = float/double
template <typename T>
inline T variantAsFloat(const JsonVariantData* var) {
if (!var) return 0;
switch (var->type) {
case JSON_POSITIVE_INTEGER:
case JSON_BOOLEAN:
return static_cast<T>(var->content.asInteger);
case JSON_NEGATIVE_INTEGER:
return -static_cast<T>(var->content.asInteger);
case JSON_LINKED_STRING:
case JSON_OWNED_STRING:
return parseFloat<T>(var->content.asString);
case JSON_FLOAT:
return static_cast<T>(var->content.asFloat);
default:
return 0;
}
}
inline const char* variantAsString(const JsonVariantData* var) {
if (!var) return 0;
if (var &&
(var->type == JSON_LINKED_STRING || var->type == JSON_OWNED_STRING))
return var->content.asString;
else
return 0;
}
inline JsonArrayData* variantAsArray(JsonVariantData* var) {
if (var && var->type == JSON_ARRAY)
return &var->content.asArray;
else
return 0;
}
inline const JsonArrayData* variantAsArray(const JsonVariantData* var) {
if (var && var->type == JSON_ARRAY)
return &var->content.asArray;
else
return 0;
}
inline JsonObjectData* variantAsObject(JsonVariantData* var) {
if (var && var->type == JSON_OBJECT)
return &var->content.asObject;
else
return 0;
}
inline const JsonObjectData* variantAsObject(const JsonVariantData* var) {
if (var && var->type == JSON_OBJECT)
return &var->content.asObject;
else
return 0;
}
inline bool variantSetBoolean(JsonVariantData* var, bool value) {
if (!var) return false;
var->type = JSON_BOOLEAN;
var->content.asInteger = static_cast<JsonUInt>(value);
return true;
}
inline bool variantSetFloat(JsonVariantData* var, JsonFloat value) {
if (!var) return false;
var->type = JSON_FLOAT;
var->content.asFloat = value;
return true;
}
template <typename T>
inline bool variantSetSignedInteger(JsonVariantData* var, T value) {
if (!var) return false;
if (value >= 0) {
var->type = JSON_POSITIVE_INTEGER;
var->content.asInteger = static_cast<JsonUInt>(value);
} else {
var->type = JSON_NEGATIVE_INTEGER;
var->content.asInteger = ~static_cast<JsonUInt>(value) + 1;
}
return true;
}
inline bool variantSetSignedInteger(JsonVariantData* var, JsonUInt value) {
if (!var) return false;
var->type = JSON_POSITIVE_INTEGER;
var->content.asInteger = static_cast<JsonUInt>(value);
return true;
}
inline bool variantSetLinkedRaw(JsonVariantData* var,
SerializedValue<const char*> value) {
if (!var) return false;
var->type = JSON_LINKED_RAW;
var->content.asRaw.data = value.data();
var->content.asRaw.size = value.size();
return true;
}
template <typename T>
inline bool variantSetOwnedRaw(JsonVariantData* var, SerializedValue<T> value,
MemoryPool* pool) {
if (!var) return false;
const char* dup = makeString(value.data(), value.size()).save(pool);
if (dup) {
var->type = JSON_OWNED_RAW;
var->content.asRaw.data = dup;
var->content.asRaw.size = value.size();
return true;
} else {
var->type = JSON_NULL;
return false;
}
}
template <typename T>
inline bool variantSetString(JsonVariantData* var, T value, MemoryPool* pool) {
if (!var) return false;
const char* dup = value.save(pool);
if (dup) {
var->type = JSON_OWNED_STRING;
var->content.asString = dup;
return true;
} else {
var->type = JSON_NULL;
return false;
}
}
inline bool variantSetString(JsonVariantData* var, const char* value) {
if (!var) return false;
var->type = JSON_LINKED_STRING;
var->content.asString = value;
return true;
}
inline bool variantSetString(JsonVariantData* var, const char* value,
MemoryPool* pool) {
return variantSetString(var, makeString(const_cast<char*>(value)), pool);
}
inline void variantSetNull(JsonVariantData* var) {
if (var) var->type = JSON_NULL;
}
inline JsonArrayData* variantToArray(JsonVariantData* var) {
if (!var) return 0;
var->type = JSON_ARRAY;
var->content.asArray.head = 0;
var->content.asArray.tail = 0;
return &var->content.asArray;
}
inline JsonObjectData* variantToObject(JsonVariantData* var) {
if (!var) return 0;
var->type = JSON_OBJECT;
var->content.asObject.head = 0;
var->content.asObject.tail = 0;
return &var->content.asObject;
}
inline bool variantCopy(JsonVariantData* dst, const JsonVariantData* src,
MemoryPool* pool) {
if (!dst) return false;
if (!src) {
dst->type = JSON_NULL;
return true;
}
switch (src->type) {
case JSON_ARRAY:
return arrayCopy(variantToArray(dst), &src->content.asArray, pool);
case JSON_OBJECT:
return objectCopy(variantToObject(dst), &src->content.asObject, pool);
case JSON_OWNED_STRING:
return variantSetString(dst, src->content.asString, pool);
case JSON_OWNED_RAW:
return variantSetOwnedRaw(
dst,
serialized(const_cast<char*>(src->content.asRaw.data),
src->content.asRaw.size),
pool);
default:
*dst = *src;
return true;
}
}
inline bool variantIsInteger(const JsonVariantData* var) {
return var && (var->type == JSON_POSITIVE_INTEGER ||
var->type == JSON_NEGATIVE_INTEGER);
}
inline bool variantIsFloat(const JsonVariantData* var) {
return var &&
(var->type == JSON_FLOAT || var->type == JSON_POSITIVE_INTEGER ||
var->type == JSON_NEGATIVE_INTEGER);
}
inline bool variantIsString(const JsonVariantData* var) {
return var &&
(var->type == JSON_LINKED_STRING || var->type == JSON_OWNED_STRING);
}
inline bool variantIsArray(const JsonVariantData* var) {
return var && var->type == JSON_ARRAY;
}
inline bool variantIsObject(const JsonVariantData* var) {
return var && var->type == JSON_OBJECT;
}
inline bool variantIsNull(const JsonVariantData* var) {
return var == 0 || var->type == JSON_NULL;
}
inline bool variantEquals(const JsonVariantData* a, const JsonVariantData* b) {
if (a == b) return true;
if (!a || !b) return false;
if (a->type != b->type) return false;
switch (a->type) {
case JSON_LINKED_RAW:
case JSON_OWNED_RAW:
case JSON_LINKED_STRING:
case JSON_OWNED_STRING:
return !strcmp(a->content.asString, b->content.asString);
case JSON_BOOLEAN:
case JSON_POSITIVE_INTEGER:
case JSON_NEGATIVE_INTEGER:
return a->content.asInteger == b->content.asInteger;
case JSON_ARRAY:
return arrayEquals(&a->content.asArray, &b->content.asArray);
case JSON_OBJECT:
return objectEquals(&a->content.asObject, &b->content.asObject);
case JSON_FLOAT:
return a->content.asFloat == b->content.asFloat;
case JSON_NULL:
default:
return true;
}
}
} // namespace ARDUINOJSON_NAMESPACE

View File

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

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

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_NAMESPACE {
class DeserializationError {
public:
enum Code {
Ok,
IncompleteInput,
InvalidInput,
NoMemory,
NotSupported,
TooDeep
};
DeserializationError() {}
DeserializationError(Code code) : _code(code) {}
friend bool operator==(const DeserializationError& err, Code code) {
return err._code == code;
}
friend bool operator==(Code code, const DeserializationError& err) {
return err._code == code;
}
friend bool operator!=(const DeserializationError& err, Code code) {
return err._code != code;
}
friend bool operator!=(Code code, const DeserializationError& err) {
return err._code != code;
}
operator bool() const {
return _code != Ok;
}
const char* c_str() const {
switch (_code) {
case Ok:
return "Ok";
case TooDeep:
return "TooDeep";
case NoMemory:
return "NoMemory";
case InvalidInput:
return "InvalidInput";
case IncompleteInput:
return "IncompleteInput";
case NotSupported:
return "NotSupported";
default:
return "???";
}
}
private:
Code _code;
};
#if ARDUINOJSON_ENABLE_STD_STREAM
inline std::ostream& operator<<(std::ostream& s,
const DeserializationError& e) {
s << e.c_str();
return s;
}
inline std::ostream& operator<<(std::ostream& s, DeserializationError::Code c) {
s << DeserializationError(c).c_str();
return s;
}
#endif
} // namespace ARDUINOJSON_NAMESPACE

View File

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

View File

@ -0,0 +1,32 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
template <typename TIterator>
class IteratorReader {
TIterator _ptr, _end;
public:
explicit IteratorReader(TIterator begin, TIterator end)
: _ptr(begin), _end(end) {}
bool ended() const {
return _ptr == _end;
}
char read() {
return char(*_ptr++);
}
};
template <typename TInput>
inline IteratorReader<typename TInput::const_iterator> makeReader(
const TInput& input) {
return IteratorReader<typename TInput::const_iterator>(input.begin(),
input.end());
}
} // namespace ARDUINOJSON_NAMESPACE

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

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