Compare commits

...

80 Commits

Author SHA1 Message Date
21998890d4 Set version to 6.9.0 2019-02-26 08:43:45 +01:00
c9d6bd76c9 Added JsonDocument::remove() and JsonVariant::remove() 2019-02-25 13:21:10 +01:00
bc2ce178ea Added JsonVariant::clear() 2019-02-25 11:44:22 +01:00
e22e62d184 Added JsonDocument::size() 2019-02-25 11:07:01 +01:00
4181de119c Detect IncompleteInput in false, true, and null 2019-02-18 16:18:11 +01:00
56bf24e1ec Fixed JsonVariant::isNull() not returning true after set((char*)0) 2019-02-18 16:04:51 +01:00
e9b4c6289b Disambiguated the name get() with getElement() and getMember() 2019-02-15 15:53:53 +01:00
7ed92bebd3 Converted JsonArray::copyFrom()/copyTo() to free functions copyArray() 2019-02-15 15:33:04 +01:00
c3f71c1a99 Updated copyright year to 2019 2019-02-15 13:32:04 +01:00
7050ef675d Decode escaped Unicode characters like \u00DE (issue #304, PR #791) 2019-02-15 13:29:30 +01:00
070cd5b6c0 Added more tests of JsonVariant::is<T>() 2019-02-01 11:28:27 +01:00
2c2cc33c94 Updated version in Arduino Library badge 2019-01-30 16:42:21 +01:00
169c83431c Set version to 6.8.0-beta 2019-01-30 16:39:38 +01:00
5f72c68d87 Updated publish script for the "ardu-badge" 2019-01-30 15:23:55 +01:00
b184af6d00 User can now use a JsonString as a key or a value 2019-01-29 17:00:11 +01:00
6f55d1e58f JsonVariant automatically promotes to JsonObject or JsonArray on write 2019-01-29 14:09:09 +01:00
5aea1363cc Merge branch 'master' into 6.x 2019-01-24 21:07:02 +01:00
0685a36f0e Added ArduBadge badge 2019-01-24 20:55:55 +01:00
70739f5cfd Reduced the size of the pretty JSON serializer 2019-01-23 18:19:24 +01:00
933a66a070 Added JsonDocument::operator[] 2019-01-23 11:43:29 +01:00
4167b11434 Create or assign a JsonDocument from a JsonArray/JsonObject/JsonVariant 2019-01-23 10:47:20 +01:00
2a3b51ac3a Fixed uninitialized variant in JsonDocument 2019-01-20 14:35:22 +01:00
e633292df1 Replaced JsonDocument::nestingLimit with a param to deserializeJson() 2019-01-19 14:45:16 +01:00
30b94493bb Added nesting() to JsonArray, JsonDocument, JsonObject, and JsonVariant 2019-01-17 09:55:51 +01:00
c51cc91f92 Added memoryUsage() to JsonArray, JsonObject, and JsonVariant 2019-01-16 09:50:57 +01:00
8b04046321 Import JsonDocument into the ArduinoJson namespace 2019-01-15 12:04:48 +01:00
11bb5e26ff Fixed copying from JsonObjectConst and JsonArrayConst 2019-01-14 11:17:57 +01:00
9ac2ac303c Removed default capacity of DynamicJsonDocument 2019-01-14 10:32:19 +01:00
f0784d3b41 Simplified deserializeJson() and deserializeMsgPack() 2019-01-04 12:33:39 +01:00
3d8ece8c8b Improved syntax highlighting in Arduino IDE 2018-12-14 17:35:40 +01:00
b0fb71f7d8 Import functions in the ArduinoJson namespace to get clearer errors 2018-12-14 17:34:49 +01:00
a5cd1b1693 Set version to 6.7.0-beta 2018-12-07 12:23:02 +01:00
d8a1eec530 Renamed JsonKey to JsonString 2018-12-07 12:08:30 +01:00
e20c47c57b DynamicJsonDocument reallocates memory pool is it's too small 2018-12-07 10:38:58 +01:00
b77b203935 Extracted VariantData and CollectionData classes 2018-12-07 09:16:58 +01:00
1ad97ebf85 Merge branch 'master' into 6.x 2018-12-04 16:52:15 +01:00
ef12c74771 Set version to 5.13.4 2018-12-04 11:36:16 +01:00
0bc03e8071 Removed spurious files in the Particle library 2018-12-04 11:19:22 +01:00
04286f3228 Moved size measurements to github.com/bblanchon/ArduinoJson-size 2018-12-04 10:50:45 +01:00
1d942cdf41 Use singly-linked list to reduce memory usage 2018-12-01 12:05:51 +01:00
aaf0d5c3c5 Renamed and moved internal files 2018-11-30 17:53:54 +01:00
04e8acd844 Store offset between slots to reduce memory usage 2018-11-30 14:28:00 +01:00
8ff48dde73 Moved size measurements to github.com/bblanchon/ArduinoJson-size 2018-11-30 14:27:35 +01:00
41b2e629f7 Increased test coverage 2018-11-30 14:27:35 +01:00
a60162ba76 Removed the indirection via StringSlot 2018-11-30 14:27:35 +01:00
45f4e5ac20 Restored the monotonic allocator 2018-11-30 14:27:33 +01:00
637f7a5bfa Removed template parameter of CharPointerReader and StringMover 2018-11-16 16:24:36 +01:00
399ccec645 Added a CSV showing the evolution of the size of the sample programs 2018-11-16 15:08:53 +01:00
2bd280df80 Removed the automatic expansion of DynamicJsonDocument 2018-11-16 10:26:59 +01:00
c832edbda3 Added script to compile samples on wandbox.org 2018-11-14 18:02:01 +01:00
b8d0041851 Set version to 6.6.0-beta 2018-11-13 18:05:59 +01:00
0a97d4c825 Added DeserializationError::code() to be used in switch statements (closes #846) 2018-11-13 14:31:53 +01:00
5eee947ffe Increased test coverage of MessagePack serialization 2018-11-12 21:36:39 +01:00
720e6548c7 Replacing a value now releases the memory 2018-11-12 18:28:34 +01:00
f375459d53 JsonArray::remove() and JsonObject::remove() now release the memory of strings 2018-11-09 18:20:57 +01:00
e842838a23 fix a spelling error of JsonParserExample.ino 2018-10-25 17:22:23 +02:00
00aa038818 Added executable msgpack_fuzzer 2018-10-19 19:42:15 +02:00
eb78077a0c Travis: Added fuzzing corpus to the cache 2018-10-19 19:40:54 +02:00
d8d939660b JsonArray::remove() and JsonObject::remove() now release the memory of the variant 2018-10-19 19:40:21 +02:00
ae089dcff7 Merged the two StringBuilder classes into one 2018-10-18 17:54:33 +02:00
1a4515c0b9 Removed JsonArray::is<T>(i) and JsonArray::set(i,v)
Removed `JsonObject::is<T>(k)` and `JsonObject::set(k,v)`
Replaced `T JsonArray::get<T>(i)` with `JsonVariant JsonArray::get(i)`
Replaced `T JsonObject::get<T>(k)` with `JsonVariant JsonObject::get(k)`
2018-10-18 14:51:02 +02:00
4eee8e8bdf Reduced code size 2018-10-18 11:15:32 +02:00
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
0d4a93018b Set version to 5.13.3 2018-10-06 17:50:41 +02:00
3ca40db9f8 Added a coupon code for the book 2018-10-06 17:42:01 +02:00
ce607196d1 Travis: update osx images 2018-10-06 17:24:54 +02:00
0b3af166ae Fixed JsonVariant::is<String>() (closes #763) 2018-10-06 17:21:16 +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
fa1a40ac6e Fixed JsonVariant::is<int>() that returned true for empty strings 2018-07-05 09:53:11 +02:00
954428e341 Improved float serialization when -fsingle-precision-constant is used 2018-07-05 09:48:57 +02:00
335 changed files with 9391 additions and 5900 deletions

View File

@ -97,11 +97,19 @@ matrix:
- compiler: gcc
env: SCRIPT=coverage
- os: osx
osx_image: xcode6.4
osx_image: xcode7.3
compiler: clang
env: SCRIPT=cmake
- os: osx
osx_image: xcode7.3
osx_image: xcode8.3
compiler: clang
env: SCRIPT=cmake
- os: osx
osx_image: xcode9.4
compiler: clang
env: SCRIPT=cmake
- os: osx
osx_image: xcode10
compiler: clang
env: SCRIPT=cmake SANITIZE=address
- env: SCRIPT=arduino VERSION=1.6.7 BOARD=arduino:avr:uno
@ -117,4 +125,6 @@ matrix:
cache:
directories:
- "~/.platformio"
- "fuzzing/json_corpus"
- "fuzzing/msgpack_corpus"
script: scripts/travis/$SCRIPT.sh

View File

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

View File

@ -1,6 +1,123 @@
ArduinoJson: change log
=======================
v6.9.0 (2019-02-26)
------
* Decode escaped Unicode characters like \u00DE (issue #304, PR #791)
Many thanks to Daniel Schulte (aka @trilader) who implemented this feature.
* Added option ARDUINOJSON_DECODE_UNICODE to enable it
* Converted `JsonArray::copyFrom()/copyTo()` to free functions `copyArray()`
* Renamed `JsonArray::copyFrom()` and `JsonObject::copyFrom()` to `set()`
* Renamed `JsonArray::get()` to `getElement()`
* Renamed `JsonArray::add()` (without arg) to `addElement()`
* Renamed `JsonObject::get()` to `getMember()`
* Renamed `JsonObject::getOrCreate()` to `getOrAddMember()`
* Fixed `JsonVariant::isNull()` not returning `true` after `set((char*)0)`
* Fixed segfault after `variant.set(serialized((char*)0))`
* Detect `IncompleteInput` in `false`, `true`, and `null`
* Added `JsonDocument::size()`
* Added `JsonDocument::remove()`
* Added `JsonVariant::clear()`
* Added `JsonVariant::remove()`
v6.8.0-beta (2019-01-30)
-----------
* Import functions in the ArduinoJson namespace to get clearer errors
* Improved syntax highlighting in Arduino IDE
* Removed default capacity of `DynamicJsonDocument`
* `JsonArray::copyFrom()` accepts `JsonArrayConst`
* `JsonVariant::set()` accepts `JsonArrayConst` and `JsonObjectConst`
* `JsonDocument` was missing in the ArduinoJson namespace
* Added `memoryUsage()` to `JsonArray`, `JsonObject`, and `JsonVariant`
* Added `nesting()` to `JsonArray`, `JsonDocument`, `JsonObject`, and `JsonVariant`
* Replaced `JsonDocument::nestingLimit` with an additional parameter
to `deserializeJson()` and `deserializeMsgPack()`
* Fixed uninitialized variant in `JsonDocument`
* Fixed `StaticJsonDocument` copy constructor and copy assignment
* The copy constructor of `DynamicJsonDocument` chooses the capacity according to the memory usage of the source, not from the capacity of the source.
* Added the ability to create/assign a `StaticJsonDocument`/`DynamicJsonDocument` from a `JsonArray`/`JsonObject`/`JsonVariant`
* Added `JsonDocument::isNull()`
* Added `JsonDocument::operator[]`
* Added `ARDUINOJSON_TAB` to configure the indentation character
* Reduced the size of the pretty JSON serializer
* Added `add()`, `createNestedArray()` and `createNestedObject()` to `JsonVariant`
* `JsonVariant` automatically promotes to `JsonObject` or `JsonArray` on write.
Calling `JsonVariant::to<T>()` is not required anymore.
* `JsonDocument` now support the same operations as `JsonVariant`.
Calling `JsonDocument::as<T>()` is not required anymore.
* Fixed example `JsonHttpClient.ino`
* User can now use a `JsonString` as a key or a value
> ### BREAKING CHANGES
>
> #### `DynamicJsonDocument`'s constructor
>
> The parameter to the constructor of `DynamicJsonDocument` is now mandatory
>
> Old code:
>
> ```c++
> DynamicJsonDocument doc;
> ```
>
> New code:
>
> ```c++
> DynamicJsonDocument doc(1024);
> ```
>
> #### Nesting limit
>
> `JsonDocument::nestingLimit` was replaced with a new parameter to `deserializeJson()` and `deserializeMsgPack()`.
>
> Old code:
>
> ```c++
> doc.nestingLimit = 15;
> deserializeJson(doc, input);
> ```
>
> New code:
>
> ```c++
> deserializeJson(doc, input, DeserializationOption::NestingLimit(15));
> ```
v6.7.0-beta (2018-12-07)
-----------
* Removed the automatic expansion of `DynamicJsonDocument`, it now has a fixed capacity.
* Restored the monotonic allocator because the code was getting too big
* Reduced the memory usage
* Reduced the code size
* Renamed `JsonKey` to `JsonString`
* Removed spurious files in the Particle library
v6.6.0-beta (2018-11-13)
-----------
* Removed `JsonArray::is<T>(i)` and `JsonArray::set(i,v)`
* Removed `JsonObject::is<T>(k)` and `JsonObject::set(k,v)`
* Replaced `T JsonArray::get<T>(i)` with `JsonVariant JsonArray::get(i)`
* Replaced `T JsonObject::get<T>(k)` with `JsonVariant JsonObject::get(k)`
* Added `JSON_STRING_SIZE()`
* ~~Replacing or removing a value now releases the memory~~
* Added `DeserializationError::code()` to be used in switch statements (issue #846)
v6.5.0-beta (2018-10-13)
-----------
* Added implicit conversion from `JsonArray` and `JsonObject` to `JsonVariant`
* Allow mixed configuration in compilation units (issue #809)
* Fixed object keys not being duplicated
* `JsonPair::key()` now returns a `JsonKey`
* Increased the default capacity of `DynamicJsonDocument`
* Fixed `JsonVariant::is<String>()` (closes #763)
* Added `JsonArrayConst`, `JsonObjectConst`, and `JsonVariantConst`
* Added copy-constructor and copy-assignment-operator for `JsonDocument` (issue #827)
v6.4.0-beta (2018-09-11)
-----------
@ -78,6 +195,7 @@ 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()`

View File

@ -1,5 +1,5 @@
# ArduinoJson - arduinojson.org
# Copyright Benoit Blanchon 2014-2018
# Copyright Benoit Blanchon 2014-2019
# MIT License
cmake_minimum_required(VERSION 3.0)
@ -7,10 +7,16 @@ project(ArduinoJson)
enable_testing()
add_definitions(-DARDUINOJSON_DEBUG)
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
add_compile_options(-g -O0)
endif()
if(${COVERAGE})
set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
set(CMAKE_CXX_FLAGS "-fprofile-arcs -ftest-coverage")
endif()
include_directories(${CMAKE_CURRENT_LIST_DIR}/src)
add_subdirectory(third-party/catch)
add_subdirectory(test)
add_subdirectory(fuzzing)

View File

@ -1,7 +1,7 @@
The MIT License (MIT)
---------------------
Copyright © 2014-2018 Benoit BLANCHON
Copyright © 2014-2019 Benoit BLANCHON
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@ -2,7 +2,11 @@
---
[![Build status](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/6.x?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x) [![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=6.x)](https://travis-ci.org/bblanchon/ArduinoJson) [![Coverage Status](https://img.shields.io/coveralls/bblanchon/ArduinoJson.svg)](https://coveralls.io/r/bblanchon/ArduinoJson?branch=6.x) [![Star this project](http://githubbadges.com/star.svg?user=bblanchon&repo=ArduinoJson&style=flat&color=fff&background=007ec6)](https://github.com/bblanchon/ArduinoJson)
[![arduino-library-badge](https://www.ardu-badge.com/badge/ArduinoJson.svg?version=6.9.0)](https://www.ardu-badge.com/ArduinoJson/6.9.0)
[![Build Status](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/6.x?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
[![Build Status](https://travis-ci.org/bblanchon/ArduinoJson.svg?branch=6.x)](https://travis-ci.org/bblanchon/ArduinoJson)
[![Coverage Status](https://coveralls.io/repos/github/bblanchon/ArduinoJson/badge.svg?branch=6.x)](https://coveralls.io/github/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).
@ -60,7 +64,7 @@ Here is a program that parses a JSON document with ArduinoJson.
```c++
char json[] = "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
DynamicJsonDocument doc;
DynamicJsonDocument doc(1024);
deserializeJson(doc, json);
JsonObjectRef root = doc.as<JsonObject>();
@ -77,7 +81,7 @@ See the [tutorial on arduinojson.org](https://arduinojson.org/doc/decoding/?utm_
Here is a program that generates a JSON document with ArduinoJson:
```c++
DynamicJsonDocument doc;
DynamicJsonDocument doc(1024);
JsonObject root = doc.to<JsonObject>();
root["sensor"] = "gps";

View File

@ -1,4 +1,4 @@
version: 6.0.1.{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-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to store your project configuration in a file.
@ -15,7 +15,11 @@
#include <SD.h>
#include <SPI.h>
// Configuration that we'll store on disk
// Our configuration structure.
//
// Never use a JsonDocument to store the configuration!
// A JsonDocument is *not* a permanent storage; it's only a temporary storage
// used during the serialization phase.
struct Config {
char hostname[64];
int port;
@ -29,9 +33,9 @@ void loadConfiguration(const char *filename, Config &config) {
// Open file for reading
File file = SD.open(filename);
// Allocate the document on the stack.
// Allocate a temporary JsonDocument
// Don't forget to change the capacity to match your requirements.
// Use arduinojson.org/assistant to compute the capacity.
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<512> doc;
// Deserialize the JSON document
@ -39,16 +43,13 @@ void loadConfiguration(const char *filename, Config &config) {
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 JsonDocument to the Config
config.port = doc["port"] | 2731;
strlcpy(config.hostname, // <- destination
doc["hostname"] | "example.com", // <- source
sizeof(config.hostname)); // <- destination's capacity
// Copy values from the JsonObject to the Config
config.port = root["port"] | 2731;
strlcpy(config.hostname, // <- destination
root["hostname"] | "example.com", // <- source
sizeof(config.hostname)); // <- destination's capacity
// Close the file (File's destructor doesn't close the file)
// Close the file (Curiously, File's destructor doesn't close the file)
file.close();
}
@ -64,24 +65,21 @@ void saveConfiguration(const char *filename, const Config &config) {
return;
}
// Allocate the document on the stack.
// Allocate a temporary JsonDocument
// Don't forget to change the capacity to match your requirements.
// Use arduinojson.org/assistant to compute the capacity.
StaticJsonDocument<256> doc;
// Make our document contain an object
JsonObject root = doc.to<JsonObject>();
// Set the values in the object
root["hostname"] = config.hostname;
root["port"] = config.port;
// Set the values in the document
doc["hostname"] = config.hostname;
doc["port"] = config.port;
// Serialize JSON to file
if (serializeJson(doc, file) == 0) {
Serial.println(F("Failed to write to file"));
}
// Close the file (File's destructor doesn't close the file)
// Close the file
file.close();
}
@ -100,7 +98,7 @@ void printFile(const char *filename) {
}
Serial.println();
// Close the file (File's destructor doesn't close the file)
// Close the file
file.close();
}

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to generate a JSON document with ArduinoJson.
@ -15,7 +15,7 @@ void setup() {
//
// 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.
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<200> doc;
// StaticJsonObject allocates memory on the stack, it can be
@ -23,30 +23,30 @@ void setup() {
//
// DynamicJsonDocument doc(200);
// Make our document be an object
JsonObject root = doc.to<JsonObject>();
// Add values in the object
// Add values in the document
//
// Most of the time, you can rely on the implicit casts.
// In other case, you can do root.set<long>("time", 1351824120);
root["sensor"] = "gps";
root["time"] = 1351824120;
doc["sensor"] = "gps";
doc["time"] = 1351824120;
// Add an array.
//
JsonArray data = root.createNestedArray("data");
JsonArray data = doc.createNestedArray("data");
data.add(48.756080);
data.add(2.302038);
serializeJson(root, Serial);
// This prints:
// Generate the minified JSON and send it to the Serial port.
//
serializeJson(doc, Serial);
// The above line prints:
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
// Start a new line
Serial.println();
serializeJsonPretty(root, Serial);
// This prints:
// Generate the prettified JSON and send it to the Serial port.
//
serializeJsonPretty(doc, Serial);
// The above line prints:
// {
// "sensor": "gps",
// "time": 1351824120,

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to parse a JSON document in an HTTP response.
@ -71,7 +71,7 @@ void setup() {
}
// Allocate the JSON document
// Use arduinojson.org/assistant to compute the capacity.
// Use arduinojson.org/v6/assistant to compute the capacity.
const size_t capacity = JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2) + 60;
DynamicJsonDocument doc(capacity);
@ -84,12 +84,11 @@ void setup() {
}
// Extract values
JsonObject root = doc.as<JsonObject>();
Serial.println(F("Response:"));
Serial.println(root["sensor"].as<char*>());
Serial.println(root["time"].as<char*>());
Serial.println(root["data"][0].as<char*>());
Serial.println(root["data"][1].as<char*>());
Serial.println(doc["sensor"].as<char*>());
Serial.println(doc["time"].as<long>());
Serial.println(doc["data"][0].as<float>(), 6);
Serial.println(doc["data"][1].as<float>(), 6);
// Disconnect
client.stop();

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to deserialize a JSON document with ArduinoJson.
@ -13,21 +13,24 @@ void setup() {
// Allocate the JSON document
//
// Inside the brackets, 200 is the size of the memory pool in bytes.
// Inside the brackets, 200 is the capacity of the memory pool in bytes.
// Don't forget to change this value to match your JSON document.
// Use arduinojson.org/assistant to compute the capacity.
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<200> doc;
// StaticJsonDocument<N> allocates memory on the stack, it can be
// replaced by DynamicJsonObject which allocates in the heap.
// replaced by DynamicJsonDocument which allocates in the heap.
//
// DynamicJsonObject doc(200);
// DynamicJsonDocument doc(200);
// JSON input string.
//
// It's better to use a char[] as shown here.
// If you use a const char* or a String, ArduinoJson will
// have to make a copy of the input in the JsonBuffer.
// Using a char[], as shown here, enables the "zero-copy" mode. This mode uses
// the minimal amount of memory because the JsonDocument stores pointers to
// the input buffer.
// If you use another type of input, ArduinoJson must copy the strings from
// the input to the JsonDocument, so you need to increase the capacity of the
// JsonDocument.
char json[] =
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
@ -41,17 +44,14 @@ void setup() {
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];
// In other case, you can do doc["time"].as<long>();
const char* sensor = doc["sensor"];
long time = doc["time"];
double latitude = doc["data"][0];
double longitude = doc["data"][1];
// Print values.
Serial.println(sensor);

View File

@ -1,16 +1,16 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to implement an HTTP server that sends JSON document
// in the responses.
// This example shows how to implement an HTTP server that sends a JSON document
// in the response.
// It uses the Ethernet library but can be easily adapted for Wifi.
//
// It sends the value of the analog and digital pins.
// The JSON document looks like the following:
// The JSON document contains the values of the analog and digital pins.
// It looks like that:
// {
// "analog": [ 0, 1, 2, 3, 4, 5 ],
// "digital": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
// "analog": [0, 76, 123, 158, 192, 205],
// "digital": [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0]
// }
#include <ArduinoJson.h>
@ -51,15 +51,12 @@ void loop() {
// Read the request (we ignore the content in this example)
while (client.available()) client.read();
// Allocate the JSON document
// Use arduinojson.org/assistant to compute the capacity.
// Allocate a temporary JsonDocument
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<500> doc;
// Make our document represent an object
JsonObject root = doc.to<JsonObject>();
// Create the "analog" array
JsonArray analogValues = root.createNestedArray("analog");
JsonArray analogValues = doc.createNestedArray("analog");
for (int pin = 0; pin < 6; pin++) {
// Read the analog input
int value = analogRead(pin);
@ -69,7 +66,7 @@ void loop() {
}
// Create the "digital" array
JsonArray digitalValues = root.createNestedArray("digital");
JsonArray digitalValues = doc.createNestedArray("digital");
for (int pin = 0; pin < 14; pin++) {
// Read the digital input
int value = digitalRead(pin);
@ -79,17 +76,19 @@ void loop() {
}
Serial.print(F("Sending: "));
serializeJson(root, Serial);
serializeJson(doc, Serial);
Serial.println();
// Write response headers
client.println("HTTP/1.0 200 OK");
client.println("Content-Type: application/json");
client.println("Connection: close");
client.println(F("HTTP/1.0 200 OK"));
client.println(F("Content-Type: application/json"));
client.println(F("Connection: close"));
client.print(F("Content-Length: "));
client.println(measureJsonPretty(doc));
client.println();
// Write JSON document
serializeJsonPretty(root, client);
serializeJsonPretty(doc, client);
// Disconnect
client.stop();

View File

@ -1,14 +1,14 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to send a JSON document to a UDP socket.
// At regular interval, it sends a UDP packet that contains the status of
// analog and digital pins.
// The JSON document looks like the following:
// It looks like that:
// {
// "analog": [ 0, 1, 2, 3, 4, 5 ],
// "digital": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ]
// "analog": [0, 76, 123, 158, 192, 205],
// "digital": [1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0]
// }
//
// If you want to test this program, you need to be able to receive the UDP
@ -43,15 +43,12 @@ void setup() {
}
void loop() {
// Allocate the JSON document
// Use arduinojson.org/assistant to compute the capacity.
// Allocate a temporary JsonDocument
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<500> doc;
// Make our document represent an object
JsonObject root = doc.to<JsonObject>();
// Create the "analog" array
JsonArray analogValues = root.createNestedArray("analog");
JsonArray analogValues = doc.createNestedArray("analog");
for (int pin = 0; pin < 6; pin++) {
// Read the analog input
int value = analogRead(pin);
@ -61,7 +58,7 @@ void loop() {
}
// Create the "digital" array
JsonArray digitalValues = root.createNestedArray("digital");
JsonArray digitalValues = doc.createNestedArray("digital");
for (int pin = 0; pin < 14; pin++) {
// Read the digital input
int value = digitalRead(pin);
@ -75,11 +72,11 @@ void loop() {
Serial.print(remoteIp);
Serial.print(F(" on port "));
Serial.println(remotePort);
serializeJson(root, Serial);
serializeJson(doc, Serial);
// Send UDP packet
udp.beginPacket(remoteIp, remotePort);
serializeJson(root, udp);
serializeJson(doc, udp);
udp.println();
udp.endPacket();

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to deserialize a MessagePack document with
@ -14,9 +14,9 @@ void setup() {
// Allocate the JSON document
//
// Inside the brackets, 200 is the size of the memory pool in bytes.
// Inside the brackets, 200 is the capacity of the memory pool in bytes.
// Don't forget to change this value to match your JSON document.
// Use arduinojson.org/assistant to compute the capacity.
// Use arduinojson.org/v6/assistant to compute the capacity.
StaticJsonDocument<200> doc;
// StaticJsonObject allocates memory on the stack, it can be
@ -26,9 +26,12 @@ void setup() {
// 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.
// Using a char[], as shown here, enables the "zero-copy" mode. This mode uses
// the minimal amount of memory because the JsonDocument stores pointers to
// the input buffer.
// If you use another type of input, ArduinoJson must copy the strings from
// the input to the JsonDocument, so you need to increase the capacity of the
// JsonDocument.
uint8_t input[] = {131, 166, 115, 101, 110, 115, 111, 114, 163, 103, 112, 115,
164, 116, 105, 109, 101, 206, 80, 147, 50, 248, 164, 100,
97, 116, 97, 146, 203, 64, 72, 96, 199, 58, 188, 148,
@ -40,31 +43,23 @@ void setup() {
// "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.
// Test if parsing succeeded.
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];
// In other case, you can do doc["time"].as<long>();
const char* sensor = doc["sensor"];
long time = doc["time"];
double latitude = doc["data"][0];
double longitude = doc["data"][1];
// Print values.
Serial.println(sensor);

View File

@ -1,12 +1,12 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows the different ways you can use Flash strings with
// ArduinoJson.
//
// Use Flash strings sparingly, because ArduinoJson duplicates them in the
// JsonBuffer. Prefer plain old char*, as they are more efficient in term of
// JsonDocument. Prefer plain old char*, as they are more efficient in term of
// code size, speed, and memory usage.
#include <ArduinoJson.h>
@ -14,11 +14,10 @@
void setup() {
#ifdef PROGMEM // <- check that Flash strings are supported
DynamicJsonDocument doc;
DynamicJsonDocument doc(1024);
// You can use a Flash String as your JSON input.
// WARNING: the content of the Flash String will be duplicated in the
// JsonBuffer.
// WARNING: the strings in the input will be duplicated in the JsonDocument.
deserializeJson(doc, F("{\"sensor\":\"gps\",\"time\":1351824120,"
"\"data\":[48.756080,2.302038]}"));
JsonObject obj = doc.as<JsonObject>();
@ -29,12 +28,12 @@ void setup() {
// 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.
// JsonDocument.
obj[F("time")] = time;
// You can set a Flash String to a JsonObject or JsonArray:
// WARNING: the content of the Flash String will be duplicated in the
// JsonBuffer.
// JsonDocument.
obj["sensor"] = F("gps");
// It works with serialized() too:

View File

@ -1,20 +1,20 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows the different ways you can use String with ArduinoJson.
//
// Use String objects sparingly, because ArduinoJson duplicates them in the
// JsonBuffer. Prefer plain old char[], as they are more efficient in term of
// JsonDocument. Prefer plain old char[], as they are more efficient in term of
// code size, speed, and memory usage.
#include <ArduinoJson.h>
void setup() {
DynamicJsonDocument doc;
DynamicJsonDocument doc(1024);
// You can use a String as your JSON input.
// WARNING: the content of the String will be duplicated in the JsonBuffer.
// WARNING: the string in the input will be duplicated in the JsonDocument.
String input =
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
deserializeJson(doc, input);
@ -25,11 +25,11 @@ void setup() {
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.
// WARNING: the content of the String will be duplicated in the JsonDocument.
obj[String("time")] = time;
// You can get a String from a JsonObject or JsonArray:
// No duplication is done, at least not in the JsonBuffer.
// No duplication is done, at least not in the JsonDocument.
String sensor = obj["sensor"];
// Unfortunately, the following doesn't work (issue #118):
@ -38,14 +38,14 @@ void setup() {
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.
// WARNING: the content of the String will be duplicated in the JsonDocument.
obj["sensor"] = sensor;
// It works with serialized() too:
obj["sensor"] = serialized(sensor);
// You can also concatenate strings
// WARNING: the content of the String will be duplicated in the JsonBuffer.
// WARNING: the content of the String will be duplicated in the JsonDocument.
obj[String("sen") + "sor"] = String("gp") + "s";
// You can compare the content of a JsonObject with a String

17
fuzzing/CMakeLists.txt Normal file
View File

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

View File

@ -1,6 +1,6 @@
# CAUTION: this file is invoked by https://github.com/google/oss-fuzz
CXXFLAGS += -I../src
CXXFLAGS += -I../src -DARDUINOJSON_DEBUG
all: \
$(OUT)/json_fuzzer \

50
fuzzing/fuzzer_main.cpp Normal file
View File

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

View File

@ -1,7 +1,7 @@
#include <ArduinoJson.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
DeserializationError error = deserializeJson(doc, data, size);
if (!error) {
std::string json;

View File

@ -1,7 +1,7 @@
#include <ArduinoJson.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
DynamicJsonDocument doc;
DynamicJsonDocument doc(4096);
DeserializationError error = deserializeMsgPack(doc, data, size);
if (!error) {
std::string json;

View File

@ -1,17 +1,36 @@
# Macros
JSON_ARRAY_SIZE KEYWORD2
JSON_OBJECT_SIZE KEYWORD2
JSON_STRING_SIZE KEYWORD2
# Free functions
deserializeJson KEYWORD2
deserializeMsgPack KEYWORD2
serialized KEYWORD2
serializeJson KEYWORD2
serializeJsonPretty KEYWORD2
serializeMsgPack KEYWORD2
# Methods
add KEYWORD2
as KEYWORD2
createNestedArray KEYWORD2
createNestedObject KEYWORD2
deserializeJson KEYWORD2
deserializeMsgPack KEYWORD2
DynamicJsonDocument KEYWORD1
get KEYWORD2
JsonArray KEYWORD1
JsonObject KEYWORD1
JsonVariant KEYWORD1
serializeMsgPack KEYWORD2
serializeJson KEYWORD2
serializeJsonPretty KEYWORD2
set KEYWORD2
StaticJsonDocument KEYWORD1
to KEYWORD2
# Type names
DeserializationError KEYWORD1 DATA_TYPE
DynamicJsonDocument KEYWORD1 DATA_TYPE
JsonArray KEYWORD1 DATA_TYPE
JsonArrayConst KEYWORD1 DATA_TYPE
JsonFloat KEYWORD1 DATA_TYPE
JsonInteger KEYWORD1 DATA_TYPE
JsonObject KEYWORD1 DATA_TYPE
JsonObjectConst KEYWORD1 DATA_TYPE
JsonString KEYWORD1 DATA_TYPE
JsonUInt KEYWORD1 DATA_TYPE
JsonVariant KEYWORD1 DATA_TYPE
JsonVariantConst KEYWORD1 DATA_TYPE
StaticJsonDocument KEYWORD1 DATA_TYPE

View File

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

View File

@ -1,5 +1,5 @@
name=ArduinoJson
version=6.4.0-beta
version=6.9.0
author=Benoit Blanchon <blog.benoitblanchon.fr>
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
sentence=An efficient and elegant JSON library for Arduino.

View File

@ -1,42 +0,0 @@
#!/bin/bash
set -eu
OUTPUT="$(pwd)/sizes.csv"
echo "Tag;Date;Parser;Generator" > $OUTPUT
cd $(dirname $(dirname $0))
git tag | while read TAG
do
git checkout -q tags/$TAG
DATE=$(git log -1 --date=short --pretty=format:%cd)
PARSER_SIZE=$(arduino --verify examples/JsonParserExample/JsonParserExample.ino 2>/dev/null | grep -e 'Sketch uses' | sed 's/.*uses \([0-9]*\).\([0-9]\+\).*/\1\2/')
if [ -e 'examples/JsonGeneratorExample/JsonGeneratorExample.ino' ]; then
GENERATOR_SIZE=$(arduino --verify examples/JsonGeneratorExample/JsonGeneratorExample.ino 2>/dev/null | grep -e 'Sketch uses' | sed 's/.*uses \([0-9]*\).\([0-9]\+\).*/\1\2/')
else
GENERATOR_SIZE=""
fi
echo $TAG
if [ ! -z "$PARSER_SIZE" ]
then
echo "JsonParserExample = $PARSER_SIZE bytes"
else
echo "JsonParserExample compilation failed."
fi
if [ ! -z "$GENERATOR_SIZE" ]
then
echo "JsonGeneratorExample = $GENERATOR_SIZE bytes"
else
echo "JsonGeneratorExample compilation failed."
fi
echo "$TAG;$DATE;$PARSER_SIZE;$GENERATOR_SIZE" >> $OUTPUT
done

View File

@ -0,0 +1,18 @@
#!/usr/bin/env bash
set -eu
SOURCE_DIR="$(dirname "$0")/.."
WORK_DIR=$(mktemp -d)
trap 'rm -rf "$WORK_DIR"' EXIT
cp "$SOURCE_DIR/README.md" "$WORK_DIR/README.md"
cp "$SOURCE_DIR/CHANGELOG.md" "$WORK_DIR/CHANGELOG.md"
cp "$SOURCE_DIR/library.properties" "$WORK_DIR/library.properties"
cp "$SOURCE_DIR/LICENSE.md" "$WORK_DIR/LICENSE.txt"
cp -r "$SOURCE_DIR/src" "$WORK_DIR/"
cp -r "$SOURCE_DIR/examples" "$WORK_DIR/"
cd "$WORK_DIR"
particle library upload
particle library publish

View File

@ -7,11 +7,15 @@ cd "$(dirname "$0")/.."
VERSION="$1"
DATE=$(date +%F)
TAG="v$VERSION"
VERSION_REGEX="[0-9a-z\\.\\-]+"
update_version_in_source () {
IFS=".-" read MAJOR MINOR REVISION EXTRA < <(echo "$VERSION")
UNDERLINE=$(printf -- '-%.0s' $(seq 1 ${#TAG}))
sed -i~ -bE "s/version=$VERSION_REGEX/version=$VERSION/; s|ardu-badge.com/ArduinoJson/$VERSION_REGEX|ardu-badge.com/ArduinoJson/$VERSION|; " README.md
rm README.md*~
sed -i~ -bE "4s/HEAD/$TAG ($DATE)/; 5s/-+/$UNDERLINE/" CHANGELOG.md
rm CHANGELOG.md*~
sed -i~ -bE "s/\"version\":.*$/\"version\": \"$VERSION\",/" library.json
@ -30,7 +34,7 @@ update_version_in_source () {
}
commit_new_version () {
git add src/ArduinoJson/version.hpp CHANGELOG.md library.json library.properties
git add src/ArduinoJson/version.hpp README.md CHANGELOG.md library.json library.properties
git commit -m "Set version to $VERSION"
}
@ -47,3 +51,7 @@ update_version_in_source
commit_new_version
add_tag
push
scripts/build-arduino-package.sh
scripts/build-single-header.sh
scripts/wandbox/publish.sh "../ArduinoJson-$TAG.h"

View File

@ -16,7 +16,7 @@ fuzz() {
export ASAN_OPTIONS="detect_leaks=0"
export LLVM_PROFILE_FILE="${FUZZER}.profraw"
./${FUZZER} "$CORPUS_DIR" "$SEED_CORPUS_DIR" -max_total_time=30
./${FUZZER} "$CORPUS_DIR" "$SEED_CORPUS_DIR" -max_total_time=30 -timeout=1
llvm-profdata-${CLANG} merge -sparse ${LLVM_PROFILE_FILE} -o ${FUZZER}.profdata
llvm-cov-${CLANG} report ./${FUZZER} -instr-profile=${FUZZER}.profdata

View File

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

View File

@ -0,0 +1,59 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to deserialize a JSON document with ArduinoJson.
#include <iostream>
#include "ArduinoJson.h"
int main() {
// Root JSON object
//
// Inside the brackets, 300 is the size of the memory pool in bytes.
// Don't forget to change this value to match your JSON document.
// Use arduinojson.org/assistant to compute the capacity.
StaticJsonDocument<300> doc;
// StaticJsonDocument<N> allocates memory on the stack, it can be
// replaced by DynamicJsonObject which allocates in the heap.
//
// DynamicJsonObject doc(200);
// JSON input string.
//
// It's better to use a char[] as shown here.
// If you use a const char* or a String, ArduinoJson will
// have to make a copy of the input in the JsonBuffer.
char json[] =
"{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";
// Deserialize the JSON document
DeserializationError error = deserializeJson(doc, json);
// Test if parsing succeeds.
if (error) {
std::cerr << "deserializeJson() failed: " << error.c_str() << std::endl;
return 1;
}
// Get the root object in the document
JsonObject root = doc.as<JsonObject>();
// Fetch values.
//
// Most of the time, you can rely on the implicit casts.
// In other case, you can do doc["time"].as<long>();
const char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
double longitude = root["data"][1];
// Print values.
std::cout << sensor << std::endl;
std::cout << time << std::endl;
std::cout << latitude << std::endl;
std::cout << longitude << std::endl;
return 0;
}

View File

@ -0,0 +1,71 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
//
// This example shows how to generate a JSON document with ArduinoJson.
#include <iostream>
#include "ArduinoJson.h"
int main() {
// Allocate the JSON document
//
// Inside the brackets, 300 is the size of the memory pool in bytes.
// Don't forget to change this value to match your JSON document.
// Use arduinojson.org/assistant to compute the capacity.
StaticJsonDocument<300> doc;
// StaticJsonObject allocates memory on the stack, it can be
// replaced by DynamicJsonObject which allocates in the heap.
//
// DynamicJsonObject doc(200);
// MessagePack input string.
//
// It's better to use a char[] as shown here.
// If you use a const char* or a String, ArduinoJson will
// have to make a copy of the input in the JsonBuffer.
uint8_t input[] = {131, 166, 115, 101, 110, 115, 111, 114, 163, 103, 112, 115,
164, 116, 105, 109, 101, 206, 80, 147, 50, 248, 164, 100,
97, 116, 97, 146, 203, 64, 72, 96, 199, 58, 188, 148,
112, 203, 64, 2, 106, 146, 230, 33, 49, 169};
// This MessagePack document contains:
// {
// "sensor": "gps",
// "time": 1351824120,
// "data": [48.75608, 2.302038]
// }
// doc of the object tree.
//
// It's a reference to the JsonObject, the actual bytes are inside the
// JsonBuffer with all the other nodes of the object tree.
// Memory is freed when jsonBuffer goes out of scope.
DeserializationError error = deserializeMsgPack(doc, input);
// Test if parsing succeeds.
if (error) {
std::cerr << "deserializeMsgPack() failed: " << error.c_str() << std::endl;
return 1;
}
// Get the root object in the document
JsonObject root = doc.as<JsonObject>();
// Fetch values.
//
// Most of the time, you can rely on the implicit casts.
// In other case, you can do doc["time"].as<long>();
const char* sensor = root["sensor"];
long time = root["time"];
double latitude = root["data"][0];
double longitude = root["data"][1];
// Print values.
std::cout << sensor << std::endl;
std::cout << time << std::endl;
std::cout << latitude << std::endl;
std::cout << longitude << std::endl;
return 0;
}

View File

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

View File

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

View File

@ -1,26 +1,58 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "ArduinoJson/version.hpp"
#include "ArduinoJson/Namespace.hpp"
#include "ArduinoJson/DynamicJsonDocument.hpp"
#include "ArduinoJson/StaticJsonDocument.hpp"
#include "ArduinoJson/Array/ArrayRef.hpp"
#include "ArduinoJson/Object/ObjectRef.hpp"
#include "ArduinoJson/Variant/VariantRef.hpp"
#include "ArduinoJson/JsonObjectImpl.hpp"
#include "ArduinoJson/Document/DynamicJsonDocument.hpp"
#include "ArduinoJson/Document/StaticJsonDocument.hpp"
#include "ArduinoJson/JsonArray.hpp"
#include "ArduinoJson/JsonObject.hpp"
#include "ArduinoJson/JsonArrayImpl.hpp"
#include "ArduinoJson/JsonArraySubscript.hpp"
#include "ArduinoJson/JsonObjectSubscript.hpp"
#include "ArduinoJson/JsonVariantImpl.hpp"
#include "ArduinoJson/Array/ArrayImpl.hpp"
#include "ArduinoJson/Array/ElementProxy.hpp"
#include "ArduinoJson/Array/Utilities.hpp"
#include "ArduinoJson/Collection/CollectionImpl.hpp"
#include "ArduinoJson/Object/MemberProxy.hpp"
#include "ArduinoJson/Object/ObjectImpl.hpp"
#include "ArduinoJson/Variant/VariantAsImpl.hpp"
#include "ArduinoJson/Variant/VariantImpl.hpp"
#include "ArduinoJson/Json/JsonDeserializer.hpp"
#include "ArduinoJson/Json/JsonSerializer.hpp"
#include "ArduinoJson/Json/PrettyJsonSerializer.hpp"
#include "ArduinoJson/MsgPack/MsgPackDeserializer.hpp"
#include "ArduinoJson/MsgPack/MsgPackSerializer.hpp"
namespace ArduinoJson {
typedef ARDUINOJSON_NAMESPACE::ArrayConstRef JsonArrayConst;
typedef ARDUINOJSON_NAMESPACE::ArrayRef JsonArray;
typedef ARDUINOJSON_NAMESPACE::Float JsonFloat;
typedef ARDUINOJSON_NAMESPACE::Integer JsonInteger;
typedef ARDUINOJSON_NAMESPACE::ObjectConstRef JsonObjectConst;
typedef ARDUINOJSON_NAMESPACE::ObjectRef JsonObject;
typedef ARDUINOJSON_NAMESPACE::Pair JsonPair;
typedef ARDUINOJSON_NAMESPACE::String JsonString;
typedef ARDUINOJSON_NAMESPACE::UInt JsonUInt;
typedef ARDUINOJSON_NAMESPACE::VariantConstRef JsonVariantConst;
typedef ARDUINOJSON_NAMESPACE::VariantRef JsonVariant;
using ARDUINOJSON_NAMESPACE::copyArray;
using ARDUINOJSON_NAMESPACE::DeserializationError;
using ARDUINOJSON_NAMESPACE::deserializeJson;
using ARDUINOJSON_NAMESPACE::deserializeMsgPack;
using ARDUINOJSON_NAMESPACE::DynamicJsonDocument;
using ARDUINOJSON_NAMESPACE::JsonDocument;
using ARDUINOJSON_NAMESPACE::serialized;
using ARDUINOJSON_NAMESPACE::serializeJson;
using ARDUINOJSON_NAMESPACE::serializeJsonPretty;
using ARDUINOJSON_NAMESPACE::serializeMsgPack;
using ARDUINOJSON_NAMESPACE::StaticJsonDocument;
namespace DeserializationOption {
using ARDUINOJSON_NAMESPACE::NestingLimit;
}
} // namespace ArduinoJson

View File

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

View File

@ -0,0 +1,22 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../Object/ObjectRef.hpp"
#include "ArrayRef.hpp"
namespace ARDUINOJSON_NAMESPACE {
template <typename TArray>
inline ArrayRef ArrayShortcuts<TArray>::createNestedArray() const {
return impl()->addElement().template to<ArrayRef>();
}
template <typename TArray>
inline ObjectRef ArrayShortcuts<TArray>::createNestedObject() const {
return impl()->addElement().template to<ObjectRef>();
}
} // namespace ARDUINOJSON_NAMESPACE

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,66 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "ArrayRef.hpp"
namespace ARDUINOJSON_NAMESPACE {
// Copy a 1D array to a JsonArray
template <typename T, size_t N>
inline bool copyArray(T (&src)[N], ArrayRef dst) {
return copyArray(src, N, dst);
}
// Copy a 1D array to a JsonArray
template <typename T>
inline bool copyArray(T* src, size_t len, ArrayRef dst) {
bool ok = true;
for (size_t i = 0; i < len; i++) {
ok &= dst.add(src[i]);
}
return ok;
}
// Copy a 2D array to a JsonArray
template <typename T, size_t N1, size_t N2>
inline bool copyArray(T (&src)[N1][N2], ArrayRef dst) {
bool ok = true;
for (size_t i = 0; i < N1; i++) {
ArrayRef nestedArray = dst.createNestedArray();
for (size_t j = 0; j < N2; j++) {
ok &= nestedArray.add(src[i][j]);
}
}
return ok;
}
// Copy a JsonArray to a 1D array
template <typename T, size_t N>
inline size_t copyArray(ArrayConstRef src, T (&dst)[N]) {
return copyArray(src, dst, N);
}
// Copy a JsonArray to a 1D array
template <typename T>
inline size_t copyArray(ArrayConstRef src, T* dst, size_t len) {
size_t i = 0;
for (ArrayConstRef::iterator it = src.begin(); it != src.end() && i < len;
++it)
dst[i++] = *it;
return i;
}
// Copy a JsonArray to a 2D array
template <typename T, size_t N1, size_t N2>
inline void copyArray(ArrayConstRef src, T (&dst)[N1][N2]) {
size_t i = 0;
for (ArrayConstRef::iterator it = src.begin(); it != src.end() && i < N1;
++it) {
copyArray(it->as<ArrayConstRef>(), dst[i++]);
}
}
} // namespace ARDUINOJSON_NAMESPACE

View File

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

View File

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

View File

@ -1,9 +1,21 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#if defined(_MSC_VER)
#define ARDUINOJSON_HAS_INT64 1
#else
#define ARDUINOJSON_HAS_INT64 0
#endif
#if __cplusplus >= 201103L
#define ARDUINOJSON_HAS_LONG_LONG 1
#else
#define ARDUINOJSON_HAS_LONG_LONG 0
#endif
// Small or big machine?
#ifndef ARDUINOJSON_EMBEDDED_MODE
#if defined(ARDUINO) || defined(__IAR_SYSTEMS_ICC__) || defined(__XC) || \
@ -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
@ -53,22 +62,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
@ -120,14 +120,9 @@
#endif
#endif
#ifndef ARDUINOJSON_ENABLE_ALIGNMENT
#ifdef ARDUINO_ARCH_AVR
// alignment isn't needed for 8-bit AVR
#define ARDUINOJSON_ENABLE_ALIGNMENT 0
#else
// but most processors need pointers to be align on word size
#define ARDUINOJSON_ENABLE_ALIGNMENT 1
#endif
// Convert unicode escape sequence (\u0123) to UTF-8
#ifndef ARDUINOJSON_DECODE_UNICODE
#define ARDUINOJSON_DECODE_UNICODE 0
#endif
// Control the exponentiation threshold for big numbers
@ -141,10 +136,6 @@
#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
#endif
#ifndef ARDUINOJSON_LITTLE_ENDIAN
#if defined(_MSC_VER) || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \
@ -154,3 +145,7 @@
#define ARDUINOJSON_LITTLE_ENDIAN 0
#endif
#endif
#ifndef ARDUINOJSON_TAB
#define ARDUINOJSON_TAB " "
#endif

View File

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

View File

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

View File

@ -1,23 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Configuration.hpp"
namespace ArduinoJson {
namespace Internals {
#if ARDUINOJSON_USE_LONG_LONG
typedef long long JsonInteger;
typedef unsigned long long JsonUInt;
#elif ARDUINOJSON_USE_INT64
typedef __int64 JsonInteger;
typedef unsigned _int64 JsonUInt;
#else
typedef long JsonInteger;
typedef unsigned long JsonUInt;
#endif
}
}

View File

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

View File

@ -1,44 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include <stdlib.h> // size_t
#include "JsonFloat.hpp"
#include "JsonInteger.hpp"
namespace ArduinoJson {
namespace Internals {
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;
};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -1,161 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Numbers/parseFloat.hpp"
#include "../Numbers/parseInteger.hpp"
#include "JsonVariantContent.hpp"
#include "JsonVariantType.hpp"
namespace ArduinoJson {
namespace Internals {
struct JsonVariantData {
JsonVariantType type;
JsonVariantContent content;
JsonVariantData() {
type = JSON_NULL;
}
void setBoolean(bool value) {
type = JSON_BOOLEAN;
content.asInteger = static_cast<JsonUInt>(value);
}
void setFloat(JsonFloat value) {
type = JSON_FLOAT;
content.asFloat = value;
}
void setNegativeInteger(JsonUInt value) {
type = JSON_NEGATIVE_INTEGER;
content.asInteger = value;
}
void setPostiveInteger(JsonUInt value) {
type = JSON_POSITIVE_INTEGER;
content.asInteger = value;
}
void setOwnedString(const char *value) {
type = JSON_OWNED_STRING;
content.asString = value;
}
void setLinkedString(const char *value) {
type = JSON_LINKED_STRING;
content.asString = value;
}
void setOwnedRaw(const char *data, size_t size) {
type = JSON_OWNED_RAW;
content.asRaw.data = data;
content.asRaw.size = size;
}
void setLinkedRaw(const char *data, size_t size) {
type = JSON_LINKED_RAW;
content.asRaw.data = data;
content.asRaw.size = size;
}
void setNull() {
type = JSON_NULL;
}
JsonArrayData *toArray() {
type = JSON_ARRAY;
content.asArray.head = 0;
content.asArray.tail = 0;
return &content.asArray;
}
JsonObjectData *toObject() {
type = JSON_OBJECT;
content.asObject.head = 0;
content.asObject.tail = 0;
return &content.asObject;
}
JsonArrayData *asArray() {
return type == JSON_ARRAY ? &content.asArray : 0;
}
JsonObjectData *asObject() {
return type == JSON_OBJECT ? &content.asObject : 0;
}
template <typename T>
T asInteger() const {
switch (type) {
case JSON_POSITIVE_INTEGER:
case JSON_BOOLEAN:
return T(content.asInteger);
case JSON_NEGATIVE_INTEGER:
return T(~content.asInteger + 1);
case JSON_LINKED_STRING:
case JSON_OWNED_STRING:
return parseInteger<T>(content.asString);
case JSON_FLOAT:
return T(content.asFloat);
default:
return 0;
}
}
template <typename T>
T asFloat() const {
switch (type) {
case JSON_POSITIVE_INTEGER:
case JSON_BOOLEAN:
return static_cast<T>(content.asInteger);
case JSON_NEGATIVE_INTEGER:
return -static_cast<T>(content.asInteger);
case JSON_LINKED_STRING:
case JSON_OWNED_STRING:
return parseFloat<T>(content.asString);
case JSON_FLOAT:
return static_cast<T>(content.asFloat);
default:
return 0;
}
}
const char *asString() const {
return isString() ? content.asString : NULL;
}
bool isArray() const {
return type == JSON_ARRAY;
}
bool isBoolean() const {
return type == JSON_BOOLEAN;
}
bool isFloat() const {
return type == JSON_FLOAT || type == JSON_POSITIVE_INTEGER ||
type == JSON_NEGATIVE_INTEGER;
}
bool isInteger() const {
return type == JSON_POSITIVE_INTEGER || type == JSON_NEGATIVE_INTEGER;
}
bool isNull() const {
return type == JSON_NULL;
}
bool isObject() const {
return type == JSON_OBJECT;
}
bool isString() const {
return type == JSON_LINKED_STRING || type == JSON_OWNED_STRING;
}
};
} // namespace Internals
} // namespace ArduinoJson

View File

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

View File

@ -1,27 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ArduinoJson {
namespace Internals {
// Enumerated type to know the current type of a JsonVariant.
// The value determines which member of JsonVariantContent is used.
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
};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -1,21 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Memory/AllocableInMemoryPool.hpp"
#include "JsonVariantData.hpp"
namespace ArduinoJson {
namespace Internals {
struct Slot : AllocableInMemoryPool {
JsonVariantData value;
struct Slot* next;
struct Slot* prev;
const char* key;
};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
@ -8,8 +8,7 @@
#include <Stream.h>
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
struct ArduinoStreamReader {
Stream& _stream;
@ -35,7 +34,6 @@ struct ArduinoStreamReader {
inline ArduinoStreamReader makeReader(Stream& input) {
return ArduinoStreamReader(input);
}
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE
#endif

View File

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

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
@ -8,9 +8,13 @@
#include <ostream>
#endif
namespace ArduinoJson {
namespace ARDUINOJSON_NAMESPACE {
class DeserializationError {
// safe bool idiom
typedef void (DeserializationError::*bool_type)() const;
void safeBoolHelper() const {}
public:
enum Code {
Ok,
@ -22,26 +26,52 @@ class DeserializationError {
};
DeserializationError() {}
DeserializationError(Code code) : _code(code) {}
DeserializationError(Code c) : _code(c) {}
friend bool operator==(const DeserializationError& err, Code code) {
return err._code == code;
// Compare with DeserializationError
friend bool operator==(const DeserializationError& lhs,
const DeserializationError& rhs) {
return lhs._code == rhs._code;
}
friend bool operator!=(const DeserializationError& lhs,
const DeserializationError& rhs) {
return lhs._code != rhs._code;
}
friend bool operator==(Code code, const DeserializationError& err) {
return err._code == code;
// Compare with Code
friend bool operator==(const DeserializationError& lhs, Code rhs) {
return lhs._code == rhs;
}
friend bool operator==(Code lhs, const DeserializationError& rhs) {
return lhs == rhs._code;
}
friend bool operator!=(const DeserializationError& lhs, Code rhs) {
return lhs._code != rhs;
}
friend bool operator!=(Code lhs, const DeserializationError& rhs) {
return lhs != rhs._code;
}
friend bool operator!=(const DeserializationError& err, Code code) {
return err._code != code;
// Behaves like a bool
operator bool_type() const {
return _code != Ok ? &DeserializationError::safeBoolHelper : 0;
}
friend bool operator==(bool value, const DeserializationError& err) {
return static_cast<bool>(err) == value;
}
friend bool operator==(const DeserializationError& err, bool value) {
return static_cast<bool>(err) == value;
}
friend bool operator!=(bool value, const DeserializationError& err) {
return static_cast<bool>(err) != value;
}
friend bool operator!=(const DeserializationError& err, bool value) {
return static_cast<bool>(err) != value;
}
friend bool operator!=(Code code, const DeserializationError& err) {
return err._code != code;
}
operator bool() const {
return _code != Ok;
// Returns internal enum, useful for switch statement
Code code() const {
return _code;
}
const char* c_str() const {
@ -80,4 +110,4 @@ inline std::ostream& operator<<(std::ostream& s, DeserializationError::Code c) {
}
#endif
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,13 +1,12 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#if ARDUINOJSON_ENABLE_PROGMEM
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
class UnsafeFlashStringReader {
const char* _ptr;
@ -50,7 +49,6 @@ inline SafeFlashStringReader makeReader(const __FlashStringHelper* input,
size_t size) {
return SafeFlashStringReader(input, size);
}
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE
#endif

View File

@ -1,11 +1,10 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename TIterator>
class IteratorReader {
@ -30,5 +29,4 @@ inline IteratorReader<typename TInput::const_iterator> makeReader(
return IteratorReader<typename TInput::const_iterator>(input.begin(),
input.end());
}
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,17 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../Configuration.hpp"
namespace ARDUINOJSON_NAMESPACE {
struct NestingLimit {
NestingLimit() : value(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
explicit NestingLimit(uint8_t n) : value(n) {}
uint8_t value;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
@ -8,8 +8,7 @@
#include <istream>
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
class StdStreamReader {
std::istream& _stream;
@ -34,7 +33,6 @@ class StdStreamReader {
inline StdStreamReader makeReader(std::istream& input) {
return StdStreamReader(input);
}
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE
#endif

View File

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

View File

@ -0,0 +1,69 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "JsonDocument.hpp"
#include <stdlib.h> // malloc, free
namespace ARDUINOJSON_NAMESPACE {
class DynamicJsonDocument : public JsonDocument {
public:
explicit DynamicJsonDocument(size_t capa) : JsonDocument(allocPool(capa)) {}
DynamicJsonDocument(const DynamicJsonDocument& src)
: JsonDocument(allocPool(src.memoryUsage())) {
set(src);
}
template <typename T>
DynamicJsonDocument(const T& src,
typename enable_if<IsVisitable<T>::value>::type* = 0)
: JsonDocument(allocPool(src.memoryUsage())) {
set(src);
}
// disambiguate
DynamicJsonDocument(VariantRef src)
: JsonDocument(allocPool(src.memoryUsage())) {
set(src);
}
~DynamicJsonDocument() {
freePool();
}
DynamicJsonDocument& operator=(const DynamicJsonDocument& src) {
reallocPoolIfTooSmall(src.memoryUsage());
set(src);
return *this;
}
template <typename T>
DynamicJsonDocument& operator=(const T& src) {
reallocPoolIfTooSmall(src.memoryUsage());
set(src);
return *this;
}
private:
MemoryPool allocPool(size_t requiredSize) {
size_t capa = addPadding(requiredSize);
return MemoryPool(reinterpret_cast<char*>(malloc(capa)), capa);
}
void reallocPoolIfTooSmall(size_t requiredSize) {
if (requiredSize <= capacity()) return;
freePool();
replacePool(allocPool(addPadding(requiredSize)));
}
void freePool() {
free(memoryPool().buffer());
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

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

View File

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

View File

@ -1,64 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Data/JsonVariantTo.hpp"
#include "JsonVariant.hpp"
#include "Memory/DynamicMemoryPool.hpp"
namespace ArduinoJson {
class DynamicJsonDocument {
public:
uint8_t nestingLimit;
DynamicJsonDocument() : nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
DynamicJsonDocument(size_t capacity)
: nestingLimit(ARDUINOJSON_DEFAULT_NESTING_LIMIT),
_memoryPool(capacity) {}
template <typename T>
bool is() const {
return getVariant().is<T>();
}
template <typename T>
typename Internals::JsonVariantAs<T>::type as() const {
return getVariant().as<T>();
}
template <typename T>
typename Internals::JsonVariantTo<T>::type to() {
_memoryPool.clear();
return getVariant().to<T>();
}
void clear() {
_memoryPool.clear();
_rootData.setNull();
}
size_t memoryUsage() const {
return _memoryPool.size();
}
template <typename Visitor>
void accept(Visitor& visitor) const {
return getVariant().accept(visitor);
}
Internals::DynamicMemoryPool& memoryPool() {
return _memoryPool;
}
private:
JsonVariant getVariant() const {
return JsonVariant(&_memoryPool, &_rootData);
}
mutable Internals::DynamicMemoryPool _memoryPool;
mutable Internals::JsonVariantData _rootData;
};
} // namespace ArduinoJson

View File

@ -1,11 +1,10 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
class EscapeSequence {
public:
@ -33,5 +32,4 @@ class EscapeSequence {
return &"\"\"\\\\b\bf\fn\nr\rt\t"[excludeIdenticals ? 4 : 0];
}
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,71 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
namespace ArduinoJson {
namespace Internals {
// Decorator on top of Print to allow indented output.
// This class is used by serializeJsonPretty() but can also be used
// for your own purpose, like logging.
template <typename Print>
class IndentedPrint {
public:
explicit IndentedPrint(Print &p) : sink(&p) {
level = 0;
tabSize = 2;
isNewLine = true;
}
size_t write(uint8_t c) {
size_t n = 0;
if (isNewLine) n += writeTabs();
n += sink->write(c);
isNewLine = c == '\n';
return n;
}
size_t write(const uint8_t *s, size_t n) {
// TODO: optimize
size_t bytesWritten = 0;
while (n > 0) {
bytesWritten += write(*s++);
n--;
}
return bytesWritten;
}
// Adds one level of indentation
void indent() {
if (level < MAX_LEVEL) level++;
}
// Removes one level of indentation
void unindent() {
if (level > 0) level--;
}
// Set the number of space printed for each level of indentation
void setTabSize(uint8_t n) {
if (n < MAX_TAB_SIZE) tabSize = n & MAX_TAB_SIZE;
}
private:
Print *sink;
uint8_t level : 4;
uint8_t tabSize : 3;
bool isNewLine : 1;
size_t writeTabs() {
size_t n = 0;
for (int i = 0; i < level * tabSize; i++) n += sink->write(' ');
return n;
}
static const int MAX_LEVEL = 15; // because it's only 4 bits
static const int MAX_TAB_SIZE = 7; // because it's only 3 bits
};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -1,40 +1,43 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../Deserialization/deserialize.hpp"
#include "../JsonVariant.hpp"
#include "../Memory/MemoryPool.hpp"
#include "../Numbers/isFloat.hpp"
#include "../Numbers/isInteger.hpp"
#include "../Polyfills/type_traits.hpp"
#include "./EscapeSequence.hpp"
#include "../Variant/VariantData.hpp"
#include "EscapeSequence.hpp"
#include "Utf8.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename TReader, typename TStringStorage>
class JsonDeserializer {
typedef typename remove_reference<TStringStorage>::type::StringBuilder
StringBuilder;
public:
JsonDeserializer(MemoryPool &memoryPool, TReader reader,
JsonDeserializer(MemoryPool &pool, TReader reader,
TStringStorage stringStorage, uint8_t nestingLimit)
: _memoryPool(&memoryPool),
: _pool(&pool),
_reader(reader),
_stringStorage(stringStorage),
_nestingLimit(nestingLimit),
_loaded(false) {}
DeserializationError parse(JsonVariant variant) {
DeserializationError parse(VariantData &variant) {
DeserializationError err = skipSpacesAndComments();
if (err) return err;
switch (current()) {
case '[':
return parseArray(variant);
return parseArray(variant.toArray());
case '{':
return parseObject(variant);
return parseObject(variant.toObject());
default:
return parseValue(variant);
@ -65,12 +68,9 @@ class JsonDeserializer {
return true;
}
DeserializationError parseArray(JsonVariant variant) {
DeserializationError parseArray(CollectionData &array) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
JsonArray array = variant.to<JsonArray>();
if (array.isNull()) return DeserializationError::NoMemory;
// Check opening braket
if (!eat('[')) return DeserializationError::InvalidInput;
@ -84,12 +84,12 @@ class JsonDeserializer {
// Read each value
for (;;) {
// Allocate slot in array
JsonVariant value = array.add();
if (value.isInvalid()) return DeserializationError::NoMemory;
VariantData *value = array.add(_pool);
if (!value) return DeserializationError::NoMemory;
// 1 - Parse value
_nestingLimit--;
err = parse(value);
err = parse(*value);
_nestingLimit++;
if (err) return err;
@ -103,12 +103,9 @@ class JsonDeserializer {
}
}
DeserializationError parseObject(JsonVariant variant) {
DeserializationError parseObject(CollectionData &object) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
JsonObject object = variant.to<JsonObject>();
if (object.isNull()) return DeserializationError::NoMemory;
// Check opening brace
if (!eat('{')) return DeserializationError::InvalidInput;
@ -121,23 +118,24 @@ class JsonDeserializer {
// Read each key value pair
for (;;) {
// Allocate slot in object
VariantSlot *slot = object.addSlot(_pool);
if (!slot) return DeserializationError::NoMemory;
// Parse key
const char *key;
err = parseKey(&key);
err = parseKey(key);
if (err) return err;
slot->setOwnedKey(make_not_null(key));
// Skip spaces
err = skipSpacesAndComments();
if (err) return err; // Colon
if (!eat(':')) return DeserializationError::InvalidInput;
// Allocate slot in object
JsonVariant value = object.set(key);
if (value.isInvalid()) return DeserializationError::NoMemory;
// Parse value
_nestingLimit--;
err = parse(value);
err = parse(*slot->data());
_nestingLimit++;
if (err) return err;
@ -155,7 +153,7 @@ class JsonDeserializer {
}
}
DeserializationError parseValue(JsonVariant variant) {
DeserializationError parseValue(VariantData &variant) {
if (isQuote(current())) {
return parseStringValue(variant);
} else {
@ -163,7 +161,7 @@ class JsonDeserializer {
}
}
DeserializationError parseKey(const char **key) {
DeserializationError parseKey(const char *&key) {
if (isQuote(current())) {
return parseQuotedString(key);
} else {
@ -171,19 +169,17 @@ class JsonDeserializer {
}
}
DeserializationError parseStringValue(JsonVariant variant) {
DeserializationError parseStringValue(VariantData &variant) {
const char *value;
DeserializationError err = parseQuotedString(&value);
DeserializationError err = parseQuotedString(value);
if (err) return err;
variant.set(value);
variant.setOwnedString(make_not_null(value));
return DeserializationError::Ok;
}
DeserializationError parseQuotedString(const char **result) {
typename remove_reference<TStringStorage>::type::String str =
_stringStorage.startString();
char stopChar = current();
DeserializationError parseQuotedString(const char *&result) {
StringBuilder builder = _stringStorage.startString();
const char stopChar = current();
move();
for (;;) {
@ -196,24 +192,34 @@ class JsonDeserializer {
if (c == '\\') {
c = current();
if (c == '\0') return DeserializationError::IncompleteInput;
if (c == 'u') return DeserializationError::NotSupported;
if (c == 'u') {
#if ARDUINOJSON_DECODE_UNICODE
uint16_t codepoint;
move();
DeserializationError err = parseCodepoint(codepoint);
if (err) return err;
Utf8::encodeCodepoint(codepoint, builder);
continue;
#else
return DeserializationError::NotSupported;
#endif
}
// replace char
c = EscapeSequence::unescapeChar(c);
if (c == '\0') return DeserializationError::InvalidInput;
move();
}
str.append(c);
builder.append(c);
}
*result = str.c_str();
if (*result == NULL) return DeserializationError::NoMemory;
result = builder.complete();
if (!result) return DeserializationError::NoMemory;
return DeserializationError::Ok;
}
DeserializationError parseNonQuotedString(const char **result) {
typename remove_reference<TStringStorage>::type::String str =
_stringStorage.startString();
DeserializationError parseNonQuotedString(const char *&result) {
StringBuilder builder = _stringStorage.startString();
char c = current();
if (c == '\0') return DeserializationError::IncompleteInput;
@ -221,19 +227,19 @@ class JsonDeserializer {
if (canBeInNonQuotedString(c)) { // no quotes
do {
move();
str.append(c);
builder.append(c);
c = current();
} while (canBeInNonQuotedString(c));
} else {
return DeserializationError::InvalidInput;
}
*result = str.c_str();
if (*result == NULL) return DeserializationError::NoMemory;
result = builder.complete();
if (!result) return DeserializationError::NoMemory;
return DeserializationError::Ok;
}
DeserializationError parseNumericValue(JsonVariant result) {
DeserializationError parseNumericValue(VariantData &result) {
char buffer[64];
uint8_t n = 0;
@ -246,17 +252,41 @@ class JsonDeserializer {
buffer[n] = 0;
if (isInteger(buffer)) {
result.set(parseInteger<JsonInteger>(buffer));
} else if (isFloat(buffer)) {
result.set(parseFloat<JsonFloat>(buffer));
} else if (!strcmp(buffer, "true")) {
result.set(true);
} else if (!strcmp(buffer, "false")) {
result.set(false);
} else if (!strcmp(buffer, "null")) {
// already null
} else {
return DeserializationError::InvalidInput;
result.setInteger(parseInteger<Integer>(buffer));
return DeserializationError::Ok;
}
if (isFloat(buffer)) {
result.setFloat(parseFloat<Float>(buffer));
return DeserializationError::Ok;
}
c = buffer[0];
if (c == 't') { // true
result.setBoolean(true);
return n == 4 ? DeserializationError::Ok
: DeserializationError::IncompleteInput;
}
if (c == 'f') { // false
result.setBoolean(false);
return n == 5 ? DeserializationError::Ok
: DeserializationError::IncompleteInput;
}
if (c == 'n') { // null
// the variant is already null
return n == 4 ? DeserializationError::Ok
: DeserializationError::IncompleteInput;
}
return DeserializationError::InvalidInput;
}
DeserializationError parseCodepoint(uint16_t &codepoint) {
codepoint = 0;
for (uint8_t i = 0; i < 4; ++i) {
char digit = current();
if (!digit) return DeserializationError::IncompleteInput;
uint8_t value = decodeHex(digit);
if (value > 0x0F) return DeserializationError::InvalidInput;
codepoint = uint16_t((codepoint << 4) | value);
move();
}
return DeserializationError::Ok;
}
@ -274,6 +304,12 @@ class JsonDeserializer {
return c == '\'' || c == '\"';
}
static inline uint8_t decodeHex(char c) {
if (c < 'A') return uint8_t(c - '0');
c &= ~0x20; // uppercase
return uint8_t(c - 'A' + 10);
}
DeserializationError skipSpacesAndComments() {
for (;;) {
switch (current()) {
@ -333,37 +369,39 @@ class JsonDeserializer {
}
}
MemoryPool *_memoryPool;
MemoryPool *_pool;
TReader _reader;
TStringStorage _stringStorage;
uint8_t _nestingLimit;
char _current;
bool _loaded;
}; // namespace Internals
} // namespace Internals
};
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, const TInput &input) {
using namespace Internals;
return deserialize<JsonDeserializer>(doc, input);
template <typename TInput>
DeserializationError deserializeJson(
JsonDocument &doc, const TInput &input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, nestingLimit);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, TInput *input) {
using namespace Internals;
return deserialize<JsonDeserializer>(doc, input);
template <typename TInput>
DeserializationError deserializeJson(
JsonDocument &doc, TInput *input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, nestingLimit);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, TInput *input,
size_t inputSize) {
using namespace Internals;
return deserialize<JsonDeserializer>(doc, input, inputSize);
template <typename TInput>
DeserializationError deserializeJson(
JsonDocument &doc, TInput *input, size_t inputSize,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeJson(TDocument &doc, TInput &input) {
using namespace Internals;
return deserialize<JsonDeserializer>(doc, input);
template <typename TInput>
DeserializationError deserializeJson(
JsonDocument &doc, TInput &input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, nestingLimit);
}
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,142 +1,124 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../Misc/Visitable.hpp"
#include "../Serialization/measure.hpp"
#include "../Serialization/serialize.hpp"
#include "./JsonWriter.hpp"
#include "TextFormatter.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename TWriter>
class JsonSerializer {
public:
JsonSerializer(TWriter &writer) : _writer(writer) {}
JsonSerializer(TWriter &writer) : _formatter(writer) {}
void visitFloat(JsonFloat value) {
_writer.writeFloat(value);
}
FORCE_INLINE void visitArray(const CollectionData &array) {
write('[');
void visitArray(JsonArray array) {
_writer.beginArray();
VariantSlot *slot = array.head();
JsonArray::iterator it = array.begin();
while (it != array.end()) {
it->accept(*this);
while (slot != 0) {
slot->data()->accept(*this);
++it;
if (it == array.end()) break;
slot = slot->next();
if (slot == 0) break;
_writer.writeComma();
write(',');
}
_writer.endArray();
write(']');
}
void visitObject(JsonObject object) {
_writer.beginObject();
void visitObject(const CollectionData &object) {
write('{');
JsonObject::iterator it = object.begin();
while (it != object.end()) {
_writer.writeString(it->key());
_writer.writeColon();
it->value().accept(*this);
VariantSlot *slot = object.head();
++it;
if (it == object.end()) break;
while (slot != 0) {
_formatter.writeString(slot->key());
write(':');
slot->data()->accept(*this);
_writer.writeComma();
slot = slot->next();
if (slot == 0) break;
write(',');
}
_writer.endObject();
write('}');
}
void visitFloat(Float value) {
_formatter.writeFloat(value);
}
void visitString(const char *value) {
_writer.writeString(value);
_formatter.writeString(value);
}
void visitRawJson(const char *data, size_t n) {
// TODO
for (size_t i = 0; i < n; i++) _writer.writeRaw(data[i]);
_formatter.writeRaw(data, n);
}
void visitNegativeInteger(JsonUInt value) {
_writer.writeRaw('-');
_writer.writeInteger(value);
void visitNegativeInteger(UInt value) {
_formatter.writeNegativeInteger(value);
}
void visitPositiveInteger(JsonUInt value) {
_writer.writeInteger(value);
void visitPositiveInteger(UInt value) {
_formatter.writePositiveInteger(value);
}
void visitBoolean(bool value) {
_writer.writeBoolean(value);
_formatter.writeBoolean(value);
}
void visitNull() {
_writer.writeRaw("null");
_formatter.writeRaw("null");
}
size_t bytesWritten() const {
return _writer.bytesWritten();
return _formatter.bytesWritten();
}
protected:
void write(char c) {
_formatter.writeRaw(c);
}
void write(const char *s) {
_formatter.writeRaw(s);
}
private:
JsonWriter<TWriter> _writer;
TextFormatter<TWriter> _formatter;
};
} // namespace Internals
template <typename TSource, typename TDestination>
size_t serializeJson(const TSource &source, TDestination &destination) {
using namespace Internals;
return serialize<JsonSerializer>(source, destination);
}
template <typename TSource>
size_t serializeJson(const TSource &source, char *buffer, size_t bufferSize) {
using namespace Internals;
return serialize<JsonSerializer>(source, buffer, bufferSize);
}
template <typename TSource>
size_t measureJson(const TSource &source) {
using namespace Internals;
return measure<JsonSerializer>(source);
}
#if ARDUINOJSON_ENABLE_STD_STREAM
inline std::ostream &operator<<(std::ostream &os, const JsonArray &source) {
template <typename T>
inline typename enable_if<IsVisitable<T>::value, std::ostream &>::type
operator<<(std::ostream &os, const T &source) {
serializeJson(source, os);
return os;
}
inline std::ostream &operator<<(std::ostream &os, const JsonObject &source) {
serializeJson(source, os);
return os;
}
inline std::ostream &operator<<(std::ostream &os, const JsonVariant &source) {
serializeJson(source, os);
return os;
}
namespace Internals {
inline std::ostream &operator<<(std::ostream &os,
const JsonArraySubscript &source) {
serializeJson(source, os);
return os;
}
template <typename TKey>
inline std::ostream &operator<<(std::ostream &os,
const JsonObjectSubscript<TKey> &source) {
serializeJson(source, os);
return os;
}
} // namespace Internals
#endif
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

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

View File

@ -1,145 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "IndentedPrint.hpp"
namespace ArduinoJson {
namespace Internals {
// Converts a compact JSON string into an indented one.
template <typename TWriter>
class Prettyfier {
public:
explicit Prettyfier(IndentedPrint<TWriter>& p) : _sink(p) {
_previousChar = 0;
_inString = false;
}
size_t write(uint8_t c) {
size_t n = _inString ? handleStringChar(c) : handleMarkupChar(char(c));
_previousChar = char(c);
return n;
}
size_t write(const uint8_t* s, size_t n) {
// TODO: optimize
size_t bytesWritten = 0;
while (n > 0) {
bytesWritten += write(*s++);
n--;
}
return bytesWritten;
}
private:
Prettyfier& operator=(const Prettyfier&); // cannot be assigned
bool inEmptyBlock() {
return _previousChar == '{' || _previousChar == '[';
}
size_t handleStringChar(uint8_t c) {
bool isQuote = c == '"' && _previousChar != '\\';
if (isQuote) _inString = false;
return _sink.write(c);
}
size_t handleMarkupChar(char c) {
switch (c) {
case '{':
case '[':
return writeBlockOpen(c);
case '}':
case ']':
return writeBlockClose(c);
case ':':
return writeColon();
case ',':
return writeComma();
case '"':
return writeQuoteOpen();
default:
return writeNormalChar(c);
}
}
size_t writeBlockClose(char c) {
size_t n = 0;
n += unindentIfNeeded();
n += write(c);
return n;
}
size_t writeBlockOpen(char c) {
size_t n = 0;
n += indentIfNeeded();
n += write(c);
return n;
}
size_t writeColon() {
size_t n = 0;
n += write(": ");
return n;
}
size_t writeComma() {
size_t n = 0;
n += write(",\r\n");
return n;
}
size_t writeQuoteOpen() {
_inString = true;
size_t n = 0;
n += indentIfNeeded();
n += write('"');
return n;
}
size_t writeNormalChar(char c) {
size_t n = 0;
n += indentIfNeeded();
n += write(c);
return n;
}
size_t indentIfNeeded() {
if (!inEmptyBlock()) return 0;
_sink.indent();
return write("\r\n");
}
size_t unindentIfNeeded() {
if (inEmptyBlock()) return 0;
_sink.unindent();
return write("\r\n");
}
size_t write(char c) {
return _sink.write(static_cast<uint8_t>(c));
}
template <size_t N>
size_t write(const char (&s)[N]) {
return _sink.write(reinterpret_cast<const uint8_t*>(s), N - 1);
}
char _previousChar;
IndentedPrint<TWriter>& _sink;
bool _inString;
};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -1,50 +1,28 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <stdint.h>
#include <string.h> // for strlen
#include "../Data/JsonInteger.hpp"
#include "../Numbers/FloatParts.hpp"
#include "../Numbers/Integer.hpp"
#include "../Polyfills/attributes.hpp"
#include "./EscapeSequence.hpp"
#include "EscapeSequence.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename TWriter>
class JsonWriter {
class TextFormatter {
public:
explicit JsonWriter(TWriter &writer) : _writer(writer), _length(0) {}
explicit TextFormatter(TWriter &writer) : _writer(writer), _length(0) {}
// Returns the number of bytes sent to the TWriter implementation.
size_t bytesWritten() const {
return _length;
}
void beginArray() {
writeRaw('[');
}
void endArray() {
writeRaw(']');
}
void beginObject() {
writeRaw('{');
}
void endObject() {
writeRaw('}');
}
void writeColon() {
writeRaw(':');
}
void writeComma() {
writeRaw(',');
}
void writeBoolean(bool value) {
if (value)
writeRaw("true");
@ -72,8 +50,8 @@ class JsonWriter {
}
}
template <typename TFloat>
void writeFloat(TFloat value) {
template <typename T>
void writeFloat(T value) {
if (isnan(value)) return writeRaw("NaN");
if (value < 0.0) {
@ -83,24 +61,29 @@ class JsonWriter {
if (isinf(value)) return writeRaw("Infinity");
FloatParts<TFloat> parts(value);
FloatParts<T> parts(value);
writeInteger(parts.integral);
writePositiveInteger(parts.integral);
if (parts.decimalPlaces) writeDecimals(parts.decimal, parts.decimalPlaces);
if (parts.exponent < 0) {
writeRaw("e-");
writeInteger(-parts.exponent);
writePositiveInteger(-parts.exponent);
}
if (parts.exponent > 0) {
writeRaw('e');
writeInteger(parts.exponent);
writePositiveInteger(parts.exponent);
}
}
template <typename UInt>
void writeInteger(UInt value) {
void writeNegativeInteger(UInt value) {
writeRaw('-');
writePositiveInteger(value);
}
template <typename T>
void writePositiveInteger(T value) {
char buffer[22];
char *end = buffer + sizeof(buffer);
char *begin = end;
@ -108,7 +91,7 @@ class JsonWriter {
// write the string in reverse order
do {
*--begin = char(value % 10 + '0');
value = UInt(value / 10);
value = T(value / 10);
} while (value);
// and dump it in the right order
@ -135,10 +118,16 @@ class JsonWriter {
void writeRaw(const char *s) {
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), strlen(s));
}
void writeRaw(const char *s, size_t n) {
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), n);
}
void writeRaw(const char *begin, const char *end) {
_length += _writer.write(reinterpret_cast<const uint8_t *>(begin),
static_cast<size_t>(end - begin));
}
template <size_t N>
void writeRaw(const char (&s)[N]) {
_length += _writer.write(reinterpret_cast<const uint8_t *>(s), N - 1);
@ -152,7 +141,6 @@ class JsonWriter {
size_t _length;
private:
JsonWriter &operator=(const JsonWriter &); // cannot be assigned
TextFormatter &operator=(const TextFormatter &); // cannot be assigned
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,26 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
namespace Utf8 {
template <typename TStringBuilder>
inline void encodeCodepoint(uint16_t codepoint, TStringBuilder &str) {
if (codepoint < 0x80) {
str.append(char(codepoint));
return;
}
if (codepoint >= 0x00000800) {
str.append(char(0xe0 /*0b11100000*/ | (codepoint >> 12)));
str.append(char(((codepoint >> 6) & 0x3f /*0b00111111*/) | 0x80));
} else {
str.append(char(0xc0 /*0b11000000*/ | (codepoint >> 6)));
}
str.append(char((codepoint & 0x3f /*0b00111111*/) | 0x80));
}
} // namespace Utf8
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,270 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Data/JsonVariantData.hpp"
#include "JsonArrayIterator.hpp"
// Returns the size (in bytes) of an array with n elements.
// Can be very handy to determine the size of a StaticMemoryPool.
#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
((NUMBER_OF_ELEMENTS) * sizeof(ArduinoJson::Internals::Slot))
namespace ArduinoJson {
class JsonObject;
namespace Internals {
class JsonArraySubscript;
}
class JsonArray {
friend class JsonVariant;
public:
typedef JsonArrayIterator iterator;
FORCE_INLINE JsonArray() : _memoryPool(0), _data(0) {}
FORCE_INLINE JsonArray(Internals::MemoryPool* buf,
Internals::JsonArrayData* arr)
: _memoryPool(buf), _data(arr) {}
// Adds the specified value at the end of the array.
//
// bool add(TValue);
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
// std::string, String, JsonObject
template <typename T>
FORCE_INLINE bool add(const T& value) {
return add().set(value);
}
// Adds the specified value at the end of the array.
FORCE_INLINE bool add(JsonArray value) {
return add().set(value);
}
//
// bool add(TValue);
// TValue = char*, const char*, const FlashStringHelper*
template <typename T>
FORCE_INLINE bool add(T* value) {
return add().set(value);
}
JsonVariant add() {
if (!_data) return JsonVariant();
Internals::Slot* slot = new (_memoryPool) Internals::Slot();
if (!slot) return JsonVariant();
slot->next = 0;
if (_data->tail) {
slot->prev = _data->tail;
_data->tail->next = slot;
_data->tail = slot;
} else {
slot->prev = 0;
_data->head = slot;
_data->tail = slot;
}
return JsonVariant(_memoryPool, &slot->value);
}
FORCE_INLINE iterator begin() const {
if (!_data) return iterator();
return iterator(_memoryPool, _data->head);
}
FORCE_INLINE iterator end() const {
return iterator();
}
// Imports a 1D array
template <typename T, size_t N>
FORCE_INLINE bool copyFrom(T (&array)[N]) {
return copyFrom(array, N);
}
// Imports a 1D array
template <typename T>
bool copyFrom(T* array, size_t len) {
bool ok = true;
for (size_t i = 0; i < len; i++) {
ok &= add(array[i]);
}
return ok;
}
// Imports a 2D array
template <typename T, size_t N1, size_t N2>
bool copyFrom(T (&array)[N1][N2]) {
bool ok = true;
for (size_t i = 0; i < N1; i++) {
JsonArray nestedArray = createNestedArray();
for (size_t j = 0; j < N2; j++) {
ok &= nestedArray.add(array[i][j]);
}
}
return ok;
}
// Copy a JsonArray
bool copyFrom(JsonArray src) {
bool ok = _data != 0;
for (iterator it = src.begin(); it != src.end(); ++it) {
ok &= add(*it);
}
return ok;
}
// Exports a 1D array
template <typename T, size_t N>
FORCE_INLINE size_t copyTo(T (&array)[N]) const {
return copyTo(array, N);
}
// Exports a 1D array
template <typename T>
size_t copyTo(T* array, size_t len) const {
size_t i = 0;
for (iterator it = begin(); it != end() && i < len; ++it) array[i++] = *it;
return i;
}
// Exports a 2D array
template <typename T, size_t N1, size_t N2>
void copyTo(T (&array)[N1][N2]) const {
if (!_data) return;
size_t i = 0;
for (iterator it = begin(); it != end() && i < N1; ++it) {
it->as<JsonArray>().copyTo(array[i++]);
}
}
FORCE_INLINE JsonArray createNestedArray();
FORCE_INLINE JsonObject createNestedObject();
FORCE_INLINE Internals::JsonArraySubscript operator[](size_t index);
FORCE_INLINE const Internals::JsonArraySubscript operator[](
size_t index) const;
FORCE_INLINE bool operator==(JsonArray rhs) const {
iterator it1 = begin();
iterator it2 = rhs.begin();
for (;;) {
if (it1 == end() && it2 == rhs.end()) return true;
if (it1 == end()) return false;
if (it2 == end()) return false;
if (*it1 != *it2) return false;
++it1;
++it2;
}
}
// Gets the value at the specified index.
template <typename T>
FORCE_INLINE typename Internals::JsonVariantAs<T>::type get(
size_t index) const {
iterator it = begin() += index;
return it != end() ? it->as<T>() : T();
}
// Check the type of the value at specified index.
template <typename T>
FORCE_INLINE bool is(size_t index) const {
iterator it = begin() += index;
return it != end() ? it->is<T>() : false;
}
// Removes element at specified position.
FORCE_INLINE void remove(iterator it) {
if (!_data) return;
Internals::Slot* slot = it.internal();
if (!slot) return;
if (slot->prev)
slot->prev->next = slot->next;
else
_data->head = slot->next;
if (slot->next)
slot->next->prev = slot->prev;
else
_data->tail = slot->prev;
}
// Removes element at specified index.
FORCE_INLINE void remove(size_t index) {
remove(begin() += index);
}
// Sets the value at specified index.
//
// bool add(size_t index, const TValue&);
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
// std::string, String, JsonArrayData, JsonObject
template <typename T>
FORCE_INLINE bool set(size_t index, const T& value) {
if (!_data) return false;
return set_impl<const T&>(index, value);
}
//
// bool add(size_t index, TValue);
// TValue = char*, const char*, const FlashStringHelper*
template <typename T>
FORCE_INLINE bool set(size_t index, T* value) {
if (!_data) return false;
return set_impl<T*>(index, value);
}
// Sets the value at specified index.
//
// bool add(size_t index, JsonArray);
template <typename T>
FORCE_INLINE bool set(size_t index, JsonArray value) {
if (!_data) return false;
return get<JsonVariant>(index).set(value);
}
FORCE_INLINE size_t size() const {
if (!_data) return 0;
Internals::Slot* slot = _data->head;
size_t n = 0;
while (slot) {
slot = slot->next;
n++;
}
return n;
}
FORCE_INLINE bool isNull() const {
return _data == 0;
}
template <typename Visitor>
FORCE_INLINE void accept(Visitor& visitor) const {
if (_data)
visitor.visitArray(*this);
else
visitor.visitNull();
}
private:
template <typename TValueRef>
FORCE_INLINE bool set_impl(size_t index, TValueRef value) {
iterator it = begin() += index;
if (it == end()) return false;
return it->set(value);
}
template <typename TValueRef>
FORCE_INLINE bool add_impl(TValueRef value) {
return add().set(value);
}
Internals::MemoryPool* _memoryPool;
Internals::JsonArrayData* _data;
};
} // namespace ArduinoJson

View File

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

View File

@ -1,73 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Data/Slot.hpp"
#include "JsonVariant.hpp"
namespace ArduinoJson {
class JsonVariantPtr {
public:
JsonVariantPtr(Internals::MemoryPool *memoryPool,
Internals::JsonVariantData *data)
: _variant(memoryPool, data) {}
JsonVariant *operator->() {
return &_variant;
}
JsonVariant &operator*() {
return _variant;
}
private:
JsonVariant _variant;
};
class JsonArrayIterator {
public:
JsonArrayIterator() : _slot(0) {}
explicit JsonArrayIterator(Internals::MemoryPool *memoryPool,
Internals::Slot *iterator)
: _memoryPool(memoryPool), _slot(iterator) {}
JsonVariant operator*() const {
return JsonVariant(_memoryPool, &_slot->value);
}
JsonVariantPtr operator->() {
return JsonVariantPtr(_memoryPool, &_slot->value);
}
bool operator==(const JsonArrayIterator &other) const {
return _slot == other._slot;
}
bool operator!=(const JsonArrayIterator &other) const {
return _slot != other._slot;
}
JsonArrayIterator &operator++() {
_slot = _slot->next;
return *this;
}
JsonArrayIterator &operator+=(size_t distance) {
while (distance && _slot) {
_slot = _slot->next;
distance--;
}
return *this;
}
Internals::Slot *internal() {
return _slot;
}
private:
Internals::MemoryPool *_memoryPool;
Internals::Slot *_slot;
};
} // namespace ArduinoJson

View File

@ -1,117 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Configuration.hpp"
#include "JsonVariantBase.hpp"
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4522)
#endif
namespace ArduinoJson {
namespace Internals {
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
public:
FORCE_INLINE JsonArraySubscript(JsonArray array, size_t index)
: _array(array), _index(index) {}
FORCE_INLINE JsonArraySubscript& operator=(const JsonArraySubscript& src) {
_array.set(_index, src.as<JsonVariant>());
return *this;
}
// Replaces the value
//
// operator=(const TValue&)
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
// std::string, String, JsonArray, JsonObject
template <typename T>
FORCE_INLINE JsonArraySubscript& operator=(const T& src) {
_array.set(_index, src);
return *this;
}
//
// operator=(TValue)
// TValue = char*, const char*, const FlashStringHelper*
template <typename T>
FORCE_INLINE JsonArraySubscript& operator=(T* src) {
_array.set(_index, src);
return *this;
}
FORCE_INLINE bool isNull() const {
return _index >= _array.size();
}
template <typename T>
FORCE_INLINE typename JsonVariantAs<T>::type as() const {
return _array.get<T>(_index);
}
template <typename T>
FORCE_INLINE bool is() const {
return _array.is<T>(_index);
}
template <typename T>
FORCE_INLINE typename JsonVariantTo<T>::type to() {
return _array.get<JsonVariant>(_index).to<T>();
}
// Replaces the value
//
// bool set(const TValue&)
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
// std::string, String, JsonArray, JsonObject
template <typename TValue>
FORCE_INLINE bool set(const TValue& value) {
return _array.set(_index, value);
}
//
// bool set(TValue)
// TValue = char*, const char*, const FlashStringHelper*
template <typename TValue>
FORCE_INLINE bool set(TValue* value) {
return _array.set(_index, value);
}
template <typename Visitor>
void accept(Visitor& visitor) const {
return _array.get<JsonVariant>(_index).accept(visitor);
}
private:
JsonArray _array;
const size_t _index;
};
template <typename TImpl>
inline JsonArraySubscript JsonVariantSubscripts<TImpl>::operator[](
size_t index) {
return impl()->template as<JsonArray>()[index];
}
template <typename TImpl>
inline const JsonArraySubscript JsonVariantSubscripts<TImpl>::operator[](
size_t index) const {
return impl()->template as<JsonArray>()[index];
}
} // namespace Internals
inline Internals::JsonArraySubscript JsonArray::operator[](size_t index) {
return Internals::JsonArraySubscript(*this, index);
}
inline const Internals::JsonArraySubscript JsonArray::operator[](
size_t index) const {
return Internals::JsonArraySubscript(*this, index);
}
} // namespace ArduinoJson
#ifdef _MSC_VER
#pragma warning(pop)
#endif

View File

@ -1,385 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "./JsonObjectIterator.hpp"
// Returns the size (in bytes) of an object with n elements.
// Can be very handy to determine the size of a StaticMemoryPool.
#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
((NUMBER_OF_ELEMENTS) * sizeof(ArduinoJson::Internals::Slot))
namespace ArduinoJson {
class JsonObject {
friend class JsonVariant;
public:
typedef JsonObjectIterator iterator;
FORCE_INLINE JsonObject() : _memoryPool(0), _data(0) {}
FORCE_INLINE JsonObject(Internals::MemoryPool* buf,
Internals::JsonObjectData* object)
: _memoryPool(buf), _data(object) {}
FORCE_INLINE iterator begin() const {
if (!_data) return iterator();
return iterator(_memoryPool, _data->head);
}
void clear() {
_data->head = 0;
_data->tail = 0;
}
// Tells weither the specified key is present and associated with a value.
//
// bool containsKey(TKey);
// TKey = const std::string&, const String&
template <typename TString>
FORCE_INLINE bool containsKey(const TString& key) const {
return containsKey_impl<const TString&>(key);
}
//
// bool containsKey(TKey);
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
template <typename TString>
FORCE_INLINE bool containsKey(TString* key) const {
return containsKey_impl<TString*>(key);
}
bool copyFrom(JsonObject src) {
bool ok = _data != 0;
clear();
for (iterator it = src.begin(); it != src.end(); ++it) {
ok &= set(it->key(), it->value());
}
return ok;
}
FORCE_INLINE iterator end() const {
return iterator();
}
// Creates and adds a JsonArray.
//
// JsonArray createNestedArray(TKey);
// TKey = const std::string&, const String&
template <typename TString>
FORCE_INLINE JsonArray createNestedArray(const TString& key);
// JsonArray createNestedArray(TKey);
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
template <typename TString>
FORCE_INLINE JsonArray createNestedArray(TString* key);
// Creates and adds a JsonObject.
//
// JsonObject createNestedObject(TKey);
// TKey = const std::string&, const String&
template <typename TString>
FORCE_INLINE JsonObject createNestedObject(const TString& key) {
if (!_data) return JsonObject();
return createNestedObject_impl<const TString&>(key);
}
//
// JsonObject createNestedObject(TKey);
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
template <typename TString>
FORCE_INLINE JsonObject createNestedObject(TString* key) {
return createNestedObject_impl<TString*>(key);
}
// Gets the value associated with the specified key.
//
// TValue get<TValue>(TKey) const;
// TKey = const std::string&, const String&
// TValue = bool, char, long, int, short, float, double,
// std::string, String, JsonArray, JsonObject
template <typename TValue, typename TString>
FORCE_INLINE typename Internals::JsonVariantAs<TValue>::type get(
const TString& key) const {
return get_impl<const TString&, TValue>(key);
}
//
// TValue get<TValue>(TKey) const;
// TKey = char*, const char*, const FlashStringHelper*
// TValue = bool, char, long, int, short, float, double,
// std::string, String, JsonArray, JsonObject
template <typename TValue, typename TString>
FORCE_INLINE typename Internals::JsonVariantAs<TValue>::type get(
TString* key) const {
return get_impl<TString*, TValue>(key);
}
// Checks the type of the value associated with the specified key.
//
//
// bool is<TValue>(TKey) const;
// TKey = const std::string&, const String&
// TValue = bool, char, long, int, short, float, double,
// std::string, String, JsonArray, JsonObject
template <typename TValue, typename TString>
FORCE_INLINE bool is(const TString& key) const {
return is_impl<const TString&, TValue>(key);
}
//
// bool is<TValue>(TKey) const;
// TKey = char*, const char*, const FlashStringHelper*
// TValue = bool, char, long, int, short, float, double,
// std::string, String, JsonArray, JsonObject
template <typename TValue, typename TString>
FORCE_INLINE bool is(TString* key) const {
return is_impl<TString*, TValue>(key);
}
// Gets or sets the value associated with the specified key.
//
// JsonObjectSubscript operator[](TKey)
// TKey = const std::string&, const String&
template <typename TString>
FORCE_INLINE Internals::JsonObjectSubscript<const TString&> operator[](
const TString& key) {
return Internals::JsonObjectSubscript<const TString&>(*this, key);
}
//
// JsonObjectSubscript operator[](TKey)
// TKey = char*, const char*, char[], const char[N], const FlashStringHelper*
template <typename TString>
FORCE_INLINE Internals::JsonObjectSubscript<TString*> operator[](
TString* key) {
return Internals::JsonObjectSubscript<TString*>(*this, key);
}
// Gets the value associated with the specified key.
//
// const JsonObjectSubscript operator[](TKey) const;
// TKey = const std::string&, const String&
template <typename TString>
FORCE_INLINE const Internals::JsonObjectSubscript<const TString&> operator[](
const TString& key) const {
return Internals::JsonObjectSubscript<const TString&>(*this, key);
}
//
// const JsonObjectSubscript operator[](TKey) const;
// TKey = const char*, const char[N], const FlashStringHelper*
template <typename TString>
FORCE_INLINE const Internals::JsonObjectSubscript<TString*> operator[](
TString* key) const {
return Internals::JsonObjectSubscript<TString*>(*this, key);
}
FORCE_INLINE bool operator==(JsonObject rhs) const {
if (size() != rhs.size()) return false;
for (iterator it = begin(); it != end(); ++it) {
if (rhs.get<JsonVariant>(it->key()) != it->value()) return false;
}
return true;
}
FORCE_INLINE void remove(iterator it) {
if (!_data) return;
Internals::Slot* slot = it.internal();
if (!slot) return;
if (slot->prev)
slot->prev->next = slot->next;
else
_data->head = slot->next;
if (slot->next)
slot->next->prev = slot->prev;
else
_data->tail = slot->prev;
}
// Removes the specified key and the associated value.
//
// void remove(TKey);
// TKey = const std::string&, const String&
template <typename TString>
FORCE_INLINE void remove(const TString& key) {
remove_impl<const TString&>(key);
}
//
// void remove(TKey);
// TKey = char*, const char*, char[], const char[], const FlashStringHelper*
template <typename TString>
FORCE_INLINE void remove(TString* key) {
remove_impl<TString*>(key);
}
// Sets the specified key with the specified value.
//
// bool set(TKey, TValue);
// TKey = const std::string&, const String&
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
// std::string, String, JsonArray, JsonObject
template <typename TValue, typename TString>
FORCE_INLINE bool set(const TString& key, const TValue& value) {
return set(key).set(value);
}
//
// bool set(TKey, TValue);
// TKey = const std::string&, const String&
// TValue = char*, const char*, const FlashStringHelper*
template <typename TValue, typename TString>
FORCE_INLINE bool set(const TString& key, TValue* value) {
return set(key).set(value);
}
//
// bool set(TKey, const TValue&);
// TKey = char*, const char*, const FlashStringHelper*
// TValue = bool, long, int, short, float, double, serialized, JsonVariant,
// std::string, String, JsonArray, JsonObject
template <typename TValue, typename TString>
FORCE_INLINE bool set(TString* key, const TValue& value) {
return set(key).set(value);
}
//
// bool set(TKey, TValue);
// TKey = char*, const char*, const FlashStringHelper*
// TValue = char*, const char*, const FlashStringHelper*
template <typename TValue, typename TString>
FORCE_INLINE bool set(TString* key, TValue* value) {
return set(key).set(value);
}
template <typename TString>
FORCE_INLINE JsonVariant set(TString* key) {
return set_impl<TString*>(key);
}
template <typename TString>
FORCE_INLINE JsonVariant set(const TString& key) {
return set_impl<const TString&>(key);
}
FORCE_INLINE size_t size() const {
if (!_data) return 0;
size_t n = 0;
Internals::Slot* slot = _data->head;
while (slot) {
n++;
slot = slot->next;
}
return n;
}
FORCE_INLINE bool isNull() const {
return _data == 0;
}
template <typename Visitor>
FORCE_INLINE void accept(Visitor& visitor) const {
if (_data)
visitor.visitObject(*this);
else
visitor.visitNull();
}
private:
template <typename TStringRef>
FORCE_INLINE bool containsKey_impl(TStringRef key) const {
return findSlot<TStringRef>(key) != 0;
}
template <typename TStringRef>
FORCE_INLINE JsonArray createNestedArray_impl(TStringRef key);
template <typename TStringRef>
FORCE_INLINE JsonObject createNestedObject_impl(TStringRef key);
// Returns the list node that matches the specified key.
template <typename TStringRef>
Internals::Slot* findSlot(TStringRef key) {
if (!_data) return 0;
Internals::Slot* slot = _data->head;
while (slot) {
if (Internals::makeString(key).equals(slot->key)) break;
slot = slot->next;
}
return slot;
}
template <typename TStringRef>
FORCE_INLINE Internals::Slot* findSlot(TStringRef key) const {
return const_cast<JsonObject*>(this)->findSlot<TStringRef>(key);
}
template <typename TStringRef, typename TValue>
FORCE_INLINE typename Internals::JsonVariantAs<TValue>::type get_impl(
TStringRef key) const {
Internals::Slot* slot = findSlot<TStringRef>(key);
return slot ? JsonVariant(_memoryPool, &slot->value).as<TValue>()
: TValue();
}
template <typename TStringRef, typename TValue>
FORCE_INLINE bool is_impl(TStringRef key) const {
Internals::Slot* slot = findSlot<TStringRef>(key);
return slot ? JsonVariant(_memoryPool, &slot->value).is<TValue>() : false;
}
template <typename TStringRef>
FORCE_INLINE void remove_impl(TStringRef key) {
if (!_data) return;
Internals::Slot* slot = findSlot<TStringRef>(key);
if (!slot) return;
if (slot->prev)
slot->prev->next = slot->next;
else
_data->head = slot->next;
if (slot->next)
slot->next->prev = slot->prev;
else
_data->tail = slot->prev;
}
template <typename TStringRef>
FORCE_INLINE JsonVariant set_impl(TStringRef key) {
if (!_data) return JsonVariant();
// ignore null key
if (Internals::makeString(key).is_null()) return JsonVariant();
// search a matching key
Internals::Slot* slot = findSlot<TStringRef>(key);
if (!slot) {
// add the key
slot = new (_memoryPool) Internals::Slot();
if (!slot) return JsonVariant();
slot->next = 0;
if (_data->tail) {
slot->prev = _data->tail;
_data->tail->next = slot;
_data->tail = slot;
} else {
slot->prev = 0;
_data->head = slot;
_data->tail = slot;
}
if (!set_key(slot, key)) return JsonVariant();
}
return JsonVariant(_memoryPool, &slot->value);
}
FORCE_INLINE bool set_key(Internals::Slot* slot, const char* key) {
slot->key = key;
return true;
}
template <typename T>
FORCE_INLINE bool set_key(Internals::Slot* slot, const T& key) {
const char* dup = Internals::makeString(key).save(_memoryPool);
if (!dup) return false;
slot->key = dup;
return true;
}
mutable Internals::MemoryPool* _memoryPool;
mutable Internals::JsonObjectData* _data;
}; // namespace ArduinoJson
} // namespace ArduinoJson

View File

@ -1,33 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonArray.hpp"
#include "JsonObject.hpp"
namespace ArduinoJson {
template <typename TString>
inline JsonArray JsonObject::createNestedArray(const TString& key) {
return createNestedArray_impl<const TString&>(key);
}
template <typename TString>
inline JsonArray JsonObject::createNestedArray(TString* key) {
return createNestedArray_impl<TString*>(key);
}
template <typename TStringRef>
inline JsonArray JsonObject::createNestedArray_impl(TStringRef key) {
if (!_data) return JsonArray();
return set(key).template to<JsonArray>();
}
template <typename TStringRef>
inline JsonObject JsonObject::createNestedObject_impl(TStringRef key) {
if (!_data) return JsonObject();
return set(key).template to<JsonObject>();
}
} // namespace ArduinoJson

View File

@ -1,72 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonPair.hpp"
namespace ArduinoJson {
class JsonPairPtr {
public:
JsonPairPtr(Internals::MemoryPool *memoryPool, Internals::Slot *slot)
: _pair(memoryPool, slot) {}
const JsonPair *operator->() const {
return &_pair;
}
const JsonPair &operator*() const {
return _pair;
}
private:
JsonPair _pair;
};
class JsonObjectIterator {
public:
JsonObjectIterator() : _slot(0) {}
explicit JsonObjectIterator(Internals::MemoryPool *memoryPool,
Internals::Slot *slot)
: _memoryPool(memoryPool), _slot(slot) {}
JsonPair operator*() const {
return JsonPair(_memoryPool, _slot);
}
JsonPairPtr operator->() {
return JsonPairPtr(_memoryPool, _slot);
}
bool operator==(const JsonObjectIterator &other) const {
return _slot == other._slot;
}
bool operator!=(const JsonObjectIterator &other) const {
return _slot != other._slot;
}
JsonObjectIterator &operator++() {
if (_slot) _slot = _slot->next;
return *this;
}
JsonObjectIterator &operator+=(size_t distance) {
while (_slot && distance > 0) {
_slot = _slot->next;
distance--;
}
return *this;
}
Internals::Slot *internal() {
return _slot;
}
private:
Internals::MemoryPool *_memoryPool;
Internals::Slot *_slot;
};
} // namespace ArduinoJson

View File

@ -1,138 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Configuration.hpp"
#include "JsonVariantBase.hpp"
#include "Polyfills/type_traits.hpp"
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4522)
#endif
namespace ArduinoJson {
namespace Internals {
template <typename TStringRef>
class JsonObjectSubscript
: public JsonVariantBase<JsonObjectSubscript<TStringRef> > {
typedef JsonObjectSubscript<TStringRef> this_type;
public:
FORCE_INLINE JsonObjectSubscript(JsonObject object, TStringRef key)
: _object(object), _key(key) {}
FORCE_INLINE this_type &operator=(const this_type &src) {
_object.set(_key, src);
return *this;
}
// Set the specified value
//
// operator=(const TValue&);
// TValue = bool, char, long, int, short, float, double,
// std::string, String, JsonArray, JsonObject
template <typename TValue>
FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type
operator=(const TValue &src) {
_object.set(_key, src);
return *this;
}
//
// operator=(TValue);
// TValue = char*, const char*, const FlashStringHelper*
template <typename TValue>
FORCE_INLINE this_type &operator=(TValue *src) {
_object.set(_key, src);
return *this;
}
FORCE_INLINE bool isNull() const {
return !_object.containsKey(_key);
}
template <typename TValue>
FORCE_INLINE typename JsonVariantAs<TValue>::type as() const {
return _object.get<TValue>(_key);
}
template <typename TValue>
FORCE_INLINE bool is() const {
return _object.is<TValue>(_key);
}
template <typename TValue>
FORCE_INLINE typename JsonVariantTo<TValue>::type to() {
return _object.set(_key).template to<TValue>();
}
// Sets the specified value.
//
// bool set(const TValue&);
// TValue = bool, char, long, int, short, float, double, serialized,
// JsonVariant,
// std::string, String, JsonArray, JsonObject
template <typename TValue>
FORCE_INLINE typename enable_if<!is_array<TValue>::value, bool>::type set(
const TValue &value) {
return _object.set(_key, value);
}
//
// bool set(TValue);
// TValue = char*, const char, const FlashStringHelper*
template <typename TValue>
FORCE_INLINE bool set(const TValue *value) {
return _object.set(_key, value);
}
template <typename Visitor>
void accept(Visitor &visitor) const {
return _object.get<JsonVariant>(_key).accept(visitor);
}
private:
JsonObject _object;
TStringRef _key;
};
template <typename TImpl>
template <typename TString>
inline typename enable_if<IsString<TString>::value,
const JsonObjectSubscript<const TString &> >::type
JsonVariantSubscripts<TImpl>::operator[](const TString &key) const {
return impl()->template as<JsonObject>()[key];
}
template <typename TImpl>
template <typename TString>
inline typename enable_if<IsString<TString>::value,
JsonObjectSubscript<const TString &> >::type
JsonVariantSubscripts<TImpl>::operator[](const TString &key) {
return impl()->template as<JsonObject>()[key];
}
template <typename TImpl>
template <typename TString>
inline typename enable_if<IsString<TString *>::value,
JsonObjectSubscript<TString *> >::type
JsonVariantSubscripts<TImpl>::operator[](TString *key) {
return impl()->template as<JsonObject>()[key];
}
template <typename TImpl>
template <typename TString>
inline typename enable_if<IsString<TString *>::value,
const JsonObjectSubscript<TString *> >::type
JsonVariantSubscripts<TImpl>::operator[](TString *key) const {
return impl()->template as<JsonObject>()[key];
}
} // namespace Internals
} // namespace ArduinoJson
#ifdef _MSC_VER
#pragma warning(pop)
#endif

View File

@ -1,35 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonVariant.hpp"
namespace ArduinoJson {
// A key value pair for JsonObjectData.
class JsonPair {
public:
JsonPair(Internals::MemoryPool* memoryPool, Internals::Slot* slot) {
if (slot) {
_key = slot->key;
_value = JsonVariant(memoryPool, &slot->value);
} else {
_key = 0;
}
}
const char* key() const {
return _key;
}
JsonVariant value() const {
return _value;
}
private:
const char* _key;
JsonVariant _value;
};
} // namespace ArduinoJson

View File

@ -1,358 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include <stddef.h>
#include <stdint.h> // for uint8_t
#include "Data/JsonVariantData.hpp"
#include "JsonVariant.hpp"
#include "JsonVariantBase.hpp"
#include "Memory/MemoryPool.hpp"
#include "Polyfills/type_traits.hpp"
#include "Serialization/DynamicStringWriter.hpp"
#include "SerializedValue.hpp"
namespace ArduinoJson {
// Forward declarations.
class JsonArray;
class JsonObject;
// A variant that can be a any value serializable to a JSON value.
//
// It can be set to:
// - a boolean
// - a char, short, int or a long (signed or unsigned)
// - a string (const char*)
// - a reference to a JsonArray or JsonObject
class JsonVariant : public Internals::JsonVariantBase<JsonVariant> {
public:
// Intenal use only
FORCE_INLINE JsonVariant(Internals::MemoryPool *memoryPool,
Internals::JsonVariantData *data)
: _memoryPool(memoryPool), _data(data) {}
// Creates an uninitialized JsonVariant
FORCE_INLINE JsonVariant() : _memoryPool(0), _data(0) {}
// set(bool value)
FORCE_INLINE bool set(bool value) {
if (!_data) return false;
_data->setBoolean(value);
return true;
}
// set(double value);
// set(float value);
template <typename T>
FORCE_INLINE bool set(
T value, typename Internals::enable_if<
Internals::is_floating_point<T>::value>::type * = 0) {
if (!_data) return false;
_data->setFloat(static_cast<Internals::JsonFloat>(value));
return true;
}
// set(char)
// set(signed short)
// set(signed int)
// set(signed long)
// set(signed char)
template <typename T>
FORCE_INLINE bool set(
T value,
typename Internals::enable_if<Internals::is_integral<T>::value &&
Internals::is_signed<T>::value>::type * =
0) {
if (!_data) return false;
if (value >= 0)
_data->setPostiveInteger(static_cast<Internals::JsonUInt>(value));
else
_data->setNegativeInteger(~static_cast<Internals::JsonUInt>(value) + 1);
return true;
}
// set(unsigned short)
// set(unsigned int)
// set(unsigned long)
template <typename T>
FORCE_INLINE bool set(
T value,
typename Internals::enable_if<Internals::is_integral<T>::value &&
Internals::is_unsigned<T>::value>::type * =
0) {
if (!_data) return false;
_data->setPostiveInteger(static_cast<Internals::JsonUInt>(value));
return true;
}
// set(SerializedValue<const char *>)
FORCE_INLINE bool set(Internals::SerializedValue<const char *> value) {
if (!_data) return false;
_data->setLinkedRaw(value.data(), value.size());
return true;
}
// set(SerializedValue<std::string>)
// set(SerializedValue<String>)
// set(SerializedValue<const __FlashStringHelper*>)
template <typename T>
FORCE_INLINE bool set(
Internals::SerializedValue<T> value,
typename Internals::enable_if<
!Internals::is_same<const char *, T>::value>::type * = 0) {
if (!_data) return false;
const char *dup =
Internals::makeString(value.data(), value.size()).save(_memoryPool);
if (dup)
_data->setOwnedRaw(dup, value.size());
else
_data->setNull();
return true;
}
// set(const std::string&)
// set(const String&)
template <typename T>
FORCE_INLINE bool set(
const T &value,
typename Internals::enable_if<Internals::IsString<T>::value>::type * =
0) {
if (!_data) return false;
const char *dup = Internals::makeString(value).save(_memoryPool);
if (dup) {
_data->setOwnedString(dup);
return true;
} else {
_data->setNull();
return false;
}
}
// set(char*)
template <typename T>
FORCE_INLINE bool set(
T *value,
typename Internals::enable_if<Internals::IsString<T *>::value>::type * =
0) {
if (!_data) return false;
const char *dup = Internals::makeString(value).save(_memoryPool);
if (dup) {
_data->setOwnedString(dup);
return true;
} else {
_data->setNull();
return false;
}
}
// set(const char*);
FORCE_INLINE bool set(const char *value) {
if (!_data) return false;
_data->setLinkedString(value);
return true;
}
bool set(const JsonVariant &value);
FORCE_INLINE bool set(JsonArray array);
FORCE_INLINE bool set(const Internals::JsonArraySubscript &);
FORCE_INLINE bool set(JsonObject object);
template <typename TString>
FORCE_INLINE bool set(const Internals::JsonObjectSubscript<TString> &);
// Get the variant as the specified type.
//
// char as<char>() const;
// signed char as<signed char>() const;
// signed short as<signed short>() const;
// signed int as<signed int>() const;
// signed long as<signed long>() const;
// unsigned char as<unsigned char>() const;
// unsigned short as<unsigned short>() const;
// unsigned int as<unsigned int>() const;
// unsigned long as<unsigned long>() const;
template <typename T>
FORCE_INLINE const typename Internals::enable_if<
Internals::is_integral<T>::value, T>::type
as() const {
return _data ? _data->asInteger<T>() : T();
}
// bool as<bool>() const
template <typename T>
FORCE_INLINE const typename Internals::enable_if<
Internals::is_same<T, bool>::value, T>::type
as() const {
return _data && _data->asInteger<int>() != 0;
}
//
// double as<double>() const;
// float as<float>() const;
template <typename T>
FORCE_INLINE const typename Internals::enable_if<
Internals::is_floating_point<T>::value, T>::type
as() const {
return _data ? _data->asFloat<T>() : 0;
}
//
// const char* as<const char*>() const;
// const char* as<char*>() const;
template <typename T>
FORCE_INLINE typename Internals::enable_if<
Internals::is_same<T, const char *>::value ||
Internals::is_same<T, char *>::value,
const char *>::type
as() const {
return _data ? _data->asString() : 0;
}
//
// std::string as<std::string>() const;
// String as<String>() const;
template <typename T>
FORCE_INLINE
typename Internals::enable_if<Internals::IsWriteableString<T>::value,
T>::type
as() const {
const char *cstr = _data ? _data->asString() : 0;
if (cstr) return T(cstr);
T s;
serializeJson(*this, s);
return s;
}
//
// JsonArray as<JsonArray>() const;
// const JsonArray as<const JsonArray>() const;
template <typename T>
FORCE_INLINE typename Internals::enable_if<
Internals::is_same<typename Internals::remove_const<T>::type,
JsonArray>::value,
JsonArray>::type
as() const;
//
// JsonObject as<JsonObject>() const;
// const JsonObject as<const JsonObject>() const;
template <typename T>
FORCE_INLINE typename Internals::enable_if<
Internals::is_same<typename Internals::remove_const<T>::type,
JsonObject>::value,
T>::type
as() const;
//
// JsonVariant as<JsonVariant> const;
template <typename T>
FORCE_INLINE
typename Internals::enable_if<Internals::is_same<T, JsonVariant>::value,
T>::type
as() const {
return *this;
}
// Tells weither the variant has the specified type.
// Returns true if the variant has type type T, false otherwise.
//
// bool is<char>() const;
// bool is<signed char>() const;
// bool is<signed short>() const;
// bool is<signed int>() const;
// bool is<signed long>() const;
// bool is<unsigned char>() const;
// bool is<unsigned short>() const;
// bool is<unsigned int>() const;
// bool is<unsigned long>() const;
template <typename T>
FORCE_INLINE typename Internals::enable_if<Internals::is_integral<T>::value,
bool>::type
is() const {
return _data && _data->isInteger();
}
//
// bool is<double>() const;
// bool is<float>() const;
template <typename T>
FORCE_INLINE
typename Internals::enable_if<Internals::is_floating_point<T>::value,
bool>::type
is() const {
return _data && _data->isFloat();
}
//
// bool is<bool>() const
template <typename T>
FORCE_INLINE typename Internals::enable_if<Internals::is_same<T, bool>::value,
bool>::type
is() const {
return _data && _data->isBoolean();
}
//
// bool is<const char*>() const;
// bool is<char*>() const;
template <typename T>
FORCE_INLINE typename Internals::enable_if<
Internals::is_same<T, const char *>::value ||
Internals::is_same<T, char *>::value,
bool>::type
is() const {
return _data && _data->isString();
}
//
// bool is<JsonArray> const;
// bool is<const JsonArray> const;
template <typename T>
FORCE_INLINE typename Internals::enable_if<
Internals::is_same<typename Internals::remove_const<T>::type,
JsonArray>::value,
bool>::type
is() const {
return _data && _data->isArray();
}
//
// bool is<JsonObject> const;
// bool is<const JsonObject> const;
template <typename T>
FORCE_INLINE typename Internals::enable_if<
Internals::is_same<typename Internals::remove_const<T>::type,
JsonObject>::value,
bool>::type
is() const {
return _data && _data->isObject();
}
FORCE_INLINE bool isNull() const {
return _data == 0 || _data->isNull();
}
FORCE_INLINE bool isInvalid() const {
return _data == 0;
}
template <typename Visitor>
void accept(Visitor &visitor) const;
// Change the type of the variant
//
// JsonArray to<JsonArray>()
template <typename T>
typename Internals::enable_if<Internals::is_same<T, JsonArray>::value,
JsonArray>::type
to();
//
// JsonObject to<JsonObject>()
template <typename T>
typename Internals::enable_if<Internals::is_same<T, JsonObject>::value,
JsonObject>::type
to();
//
// JsonObject to<JsonVariant>()
template <typename T>
typename Internals::enable_if<Internals::is_same<T, JsonVariant>::value,
JsonVariant>::type
to();
private:
Internals::MemoryPool *_memoryPool;
Internals::JsonVariantData *_data;
}; // namespace ArduinoJson
} // namespace ArduinoJson

View File

@ -1,22 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "JsonVariantCasts.hpp"
#include "JsonVariantComparisons.hpp"
#include "JsonVariantOr.hpp"
#include "JsonVariantSubscripts.hpp"
namespace ArduinoJson {
namespace Internals {
template <typename TImpl>
class JsonVariantBase : public JsonVariantCasts<TImpl>,
public JsonVariantComparisons<TImpl>,
public JsonVariantOr<TImpl>,
public JsonVariantSubscripts<TImpl>,
public JsonVariantTag {};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -1,141 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Data/IsVariant.hpp"
#include "Data/JsonFloat.hpp"
#include "Data/JsonInteger.hpp"
#include "Polyfills/type_traits.hpp"
#include "Strings/StringTypes.hpp"
namespace ArduinoJson {
class JsonArray;
class JsonObject;
namespace Internals {
template <typename TImpl>
class JsonVariantComparisons {
public:
template <typename TComparand>
friend bool operator==(const JsonVariantComparisons &variant,
TComparand comparand) {
return variant.equals(comparand);
}
template <typename TComparand>
friend typename enable_if<!IsVariant<TComparand>::value, bool>::type
operator==(TComparand comparand, const JsonVariantComparisons &variant) {
return variant.equals(comparand);
}
template <typename TComparand>
friend bool operator!=(const JsonVariantComparisons &variant,
TComparand comparand) {
return !variant.equals(comparand);
}
template <typename TComparand>
friend typename enable_if<!IsVariant<TComparand>::value, bool>::type
operator!=(TComparand comparand, const JsonVariantComparisons &variant) {
return !variant.equals(comparand);
}
template <typename TComparand>
friend bool operator<=(const JsonVariantComparisons &left, TComparand right) {
return left.as<TComparand>() <= right;
}
template <typename TComparand>
friend bool operator<=(TComparand comparand,
const JsonVariantComparisons &variant) {
return comparand <= variant.as<TComparand>();
}
template <typename TComparand>
friend bool operator>=(const JsonVariantComparisons &variant,
TComparand comparand) {
return variant.as<TComparand>() >= comparand;
}
template <typename TComparand>
friend bool operator>=(TComparand comparand,
const JsonVariantComparisons &variant) {
return comparand >= variant.as<TComparand>();
}
template <typename TComparand>
friend bool operator<(const JsonVariantComparisons &varian,
TComparand comparand) {
return varian.as<TComparand>() < comparand;
}
template <typename TComparand>
friend bool operator<(TComparand comparand,
const JsonVariantComparisons &variant) {
return comparand < variant.as<TComparand>();
}
template <typename TComparand>
friend bool operator>(const JsonVariantComparisons &variant,
TComparand comparand) {
return variant.as<TComparand>() > comparand;
}
template <typename TComparand>
friend bool operator>(TComparand comparand,
const JsonVariantComparisons &variant) {
return comparand > variant.as<TComparand>();
}
private:
const TImpl *impl() const {
return static_cast<const TImpl *>(this);
}
template <typename T>
const typename JsonVariantAs<T>::type as() const {
return impl()->template as<T>();
}
template <typename T>
bool is() const {
return impl()->template is<T>();
}
template <typename TString>
typename enable_if<IsString<TString>::value, bool>::type equals(
const TString &comparand) const {
return makeString(comparand).equals(as<const char *>());
}
template <typename TComparand>
typename enable_if<
!IsVariant<TComparand>::value && !IsString<TComparand>::value, bool>::type
equals(const TComparand &comparand) const {
return as<TComparand>() == comparand;
}
template <typename TVariant2>
bool equals(const JsonVariantComparisons<TVariant2> &right) const {
using namespace Internals;
if (is<bool>() && right.template is<bool>())
return as<bool>() == right.template as<bool>();
if (is<JsonInteger>() && right.template is<JsonInteger>())
return as<JsonInteger>() == right.template as<JsonInteger>();
if (is<JsonFloat>() && right.template is<JsonFloat>())
return as<JsonFloat>() == right.template as<JsonFloat>();
if (is<JsonArray>() && right.template is<JsonArray>())
return as<JsonArray>() == right.template as<JsonArray>();
if (is<JsonObject>() && right.template is<JsonObject>())
return as<JsonObject>() == right.template as<JsonObject>();
if (is<char *>() && right.template is<char *>())
return makeString(as<char *>()).equals(right.template as<char *>());
return false;
}
};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -1,138 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Configuration.hpp"
#include "JsonVariant.hpp"
#include "Numbers/parseFloat.hpp"
#include "Numbers/parseInteger.hpp"
#include <string.h> // for strcmp
namespace ArduinoJson {
inline bool JsonVariant::set(JsonArray array) {
return to<JsonArray>().copyFrom(array);
}
inline bool JsonVariant::set(const Internals::JsonArraySubscript& value) {
return set(value.as<JsonVariant>());
}
inline bool JsonVariant::set(JsonObject object) {
return to<JsonObject>().copyFrom(object);
}
template <typename TString>
inline bool JsonVariant::set(
const Internals::JsonObjectSubscript<TString>& value) {
return set(value.template as<JsonVariant>());
}
inline bool JsonVariant::set(const JsonVariant& value) {
if (!_data) return false;
if (!value._data) {
_data->setNull();
return true;
}
switch (value._data->type) {
case Internals::JSON_ARRAY:
return set(value.as<JsonArray>());
case Internals::JSON_OBJECT:
return set(value.as<JsonObject>());
case Internals::JSON_OWNED_STRING:
return set(const_cast<char*>(value._data->content.asString));
case Internals::JSON_OWNED_RAW:
return set(serialized(const_cast<char*>(value._data->content.asRaw.data),
value._data->content.asRaw.size));
default:
*_data = *value._data;
return true;
}
}
template <typename T>
inline typename Internals::enable_if<
Internals::is_same<typename Internals::remove_const<T>::type,
JsonArray>::value,
JsonArray>::type
JsonVariant::as() const {
return _data ? JsonArray(_memoryPool, _data->asArray()) : JsonArray();
}
template <typename T>
inline typename Internals::enable_if<
Internals::is_same<typename Internals::remove_const<T>::type,
JsonObject>::value,
T>::type
JsonVariant::as() const {
return _data ? JsonObject(_memoryPool, _data->asObject()) : JsonObject();
}
template <typename T>
inline typename Internals::enable_if<Internals::is_same<T, JsonArray>::value,
JsonArray>::type
JsonVariant::to() {
if (!_data) return JsonArray();
return JsonArray(_memoryPool, _data->toArray());
}
template <typename T>
typename Internals::enable_if<Internals::is_same<T, JsonObject>::value,
JsonObject>::type
JsonVariant::to() {
if (!_data) return JsonObject();
return JsonObject(_memoryPool, _data->toObject());
}
template <typename T>
typename Internals::enable_if<Internals::is_same<T, JsonVariant>::value,
JsonVariant>::type
JsonVariant::to() {
if (!_data) return JsonVariant();
_data->setNull();
return *this;
}
template <typename Visitor>
inline void JsonVariant::accept(Visitor& visitor) const {
using namespace Internals;
if (!_data) return visitor.visitNull();
switch (_data->type) {
case JSON_FLOAT:
return visitor.visitFloat(_data->content.asFloat);
case JSON_ARRAY:
return visitor.visitArray(
JsonArray(_memoryPool, &_data->content.asArray));
case JSON_OBJECT:
return visitor.visitObject(
JsonObject(_memoryPool, &_data->content.asObject));
case JSON_LINKED_STRING:
case JSON_OWNED_STRING:
return visitor.visitString(_data->content.asString);
case JSON_LINKED_RAW:
case JSON_OWNED_RAW:
return visitor.visitRawJson(_data->content.asRaw.data,
_data->content.asRaw.size);
case JSON_NEGATIVE_INTEGER:
return visitor.visitNegativeInteger(_data->content.asInteger);
case JSON_POSITIVE_INTEGER:
return visitor.visitPositiveInteger(_data->content.asInteger);
case JSON_BOOLEAN:
return visitor.visitBoolean(_data->content.asInteger != 0);
default:
return visitor.visitNull();
}
}
} // namespace ArduinoJson

View File

@ -1,77 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "Data/JsonVariantAs.hpp"
#include "Polyfills/attributes.hpp"
#include "Polyfills/type_traits.hpp"
#include "Strings/StringTypes.hpp"
namespace ArduinoJson {
class JsonArray;
class JsonObject;
namespace Internals {
// Forward declarations.
class JsonArraySubscript;
template <typename TKey>
class JsonObjectSubscript;
template <typename TImpl>
class JsonVariantSubscripts {
public:
// Mimics an array or an object.
// Returns the size of the array or object if the variant has that type.
// Returns 0 if the variant is neither an array nor an object
size_t size() const {
return impl()->template as<JsonArray>().size() +
impl()->template as<JsonObject>().size();
}
// Mimics an array.
// Returns the element at specified index if the variant is an array.
FORCE_INLINE const JsonArraySubscript operator[](size_t index) const;
FORCE_INLINE JsonArraySubscript operator[](size_t index);
// Mimics an object.
// Returns the value associated with the specified key if the variant is
// an object.
//
// const JsonObjectSubscript operator[](TKey) const;
// TKey = const std::string&, const String&
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value,
const JsonObjectSubscript<const TString &> >::type
operator[](const TString &key) const;
//
// const JsonObjectSubscript operator[](TKey) const;
// TKey = const std::string&, const String&
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value,
JsonObjectSubscript<const TString &> >::type
operator[](const TString &key);
//
// JsonObjectSubscript operator[](TKey);
// TKey = const char*, const char[N], const FlashStringHelper*
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString *>::value,
JsonObjectSubscript<TString *> >::type
operator[](TString *key);
//
// JsonObjectSubscript operator[](TKey);
// TKey = const char*, const char[N], const FlashStringHelper*
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString *>::value,
const JsonObjectSubscript<TString *> >::type
operator[](TString *key) const;
private:
const TImpl *impl() const {
return static_cast<const TImpl *>(this);
}
};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -0,0 +1,28 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <stddef.h> // size_t
namespace ARDUINOJSON_NAMESPACE {
inline bool isAligned(void *ptr) {
const size_t mask = sizeof(void *) - 1;
size_t addr = reinterpret_cast<size_t>(ptr);
return (addr & mask) == 0;
}
inline size_t addPadding(size_t bytes) {
const size_t mask = sizeof(void *) - 1;
return (bytes + mask) & ~mask;
}
template <size_t bytes>
struct AddPadding {
static const size_t mask = sizeof(void *) - 1;
static const size_t value = (bytes + mask) & ~mask;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,21 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "MemoryPool.hpp"
namespace ArduinoJson {
namespace Internals {
class AllocableInMemoryPool {
public:
void *operator new(size_t n, MemoryPool *memoryPool) NOEXCEPT {
return memoryPool->alloc(n);
}
void operator delete(void *, MemoryPool *)NOEXCEPT {}
};
} // namespace Internals
} // namespace ArduinoJson

View File

@ -1,168 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "MemoryPool.hpp"
#include <stdlib.h>
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic push
#endif
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#endif
namespace ArduinoJson {
namespace Internals {
class DefaultAllocator {
public:
void* allocate(size_t size) {
return malloc(size);
}
void deallocate(void* pointer) {
free(pointer);
}
};
template <typename TAllocator>
class DynamicMemoryPoolBase : public MemoryPool {
struct Block;
struct EmptyBlock {
Block* next;
size_t capacity;
size_t size;
};
struct Block : EmptyBlock {
uint8_t data[1];
};
public:
enum { EmptyBlockSize = sizeof(EmptyBlock) };
DynamicMemoryPoolBase(size_t initialSize = 256)
: _head(NULL), _nextBlockCapacity(initialSize) {}
~DynamicMemoryPoolBase() {
clear();
}
// Gets the number of bytes occupied in the memoryPool
size_t size() const {
size_t total = 0;
for (const Block* b = _head; b; b = b->next) total += b->size;
return total;
}
// Allocates the specified amount of bytes in the memoryPool
virtual void* alloc(size_t bytes) {
alignNextAlloc();
return canAllocInHead(bytes) ? allocInHead(bytes) : allocInNewBlock(bytes);
}
// Resets the memoryPool.
// USE WITH CAUTION: this invalidates all previously allocated data
void clear() {
Block* currentBlock = _head;
while (currentBlock != NULL) {
_nextBlockCapacity = currentBlock->capacity;
Block* nextBlock = currentBlock->next;
_allocator.deallocate(currentBlock);
currentBlock = nextBlock;
}
_head = 0;
}
class String {
public:
String(DynamicMemoryPoolBase* parent)
: _parent(parent), _start(NULL), _length(0) {}
void append(char c) {
if (_parent->canAllocInHead(1)) {
char* end = static_cast<char*>(_parent->allocInHead(1));
*end = c;
if (_length == 0) _start = end;
} else {
char* newStart =
static_cast<char*>(_parent->allocInNewBlock(_length + 1));
if (_start && newStart) memcpy(newStart, _start, _length);
if (newStart) newStart[_length] = c;
_start = newStart;
}
_length++;
}
const char* c_str() {
append(0);
return _start;
}
private:
DynamicMemoryPoolBase* _parent;
char* _start;
size_t _length;
};
String startString() {
return String(this);
}
private:
void alignNextAlloc() {
if (_head) _head->size = this->round_size_up(_head->size);
}
bool canAllocInHead(size_t bytes) const {
return _head != NULL && _head->size + bytes <= _head->capacity;
}
void* allocInHead(size_t bytes) {
void* p = _head->data + _head->size;
_head->size += bytes;
return p;
}
void* allocInNewBlock(size_t bytes) {
size_t capacity = _nextBlockCapacity;
if (bytes > capacity) capacity = bytes;
if (!addNewBlock(capacity)) return NULL;
_nextBlockCapacity *= 2;
return allocInHead(bytes);
}
bool addNewBlock(size_t capacity) {
size_t bytes = EmptyBlockSize + capacity;
Block* block = static_cast<Block*>(_allocator.allocate(bytes));
if (block == NULL) return false;
block->capacity = capacity;
block->size = 0;
block->next = _head;
_head = block;
return true;
}
TAllocator _allocator;
Block* _head;
size_t _nextBlockCapacity;
};
// Implements a MemoryPool with dynamic memory allocation.
// You are strongly encouraged to consider using StaticMemoryPool which is much
// more suitable for embedded systems.
typedef DynamicMemoryPoolBase<DefaultAllocator> DynamicMemoryPool;
} // namespace Internals
} // namespace ArduinoJson
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic pop
#endif
#endif

View File

@ -1,42 +1,120 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <stddef.h> // for size_t
#include <stdint.h> // for uint8_t
#include <string.h>
#include "../Polyfills/assert.hpp"
#include "../Polyfills/mpl/max.hpp"
#include "../Variant/VariantSlot.hpp"
#include "Alignment.hpp"
#include "MemoryPool.hpp"
#include "StringSlot.hpp"
#include "../Configuration.hpp"
#include "../Polyfills/attributes.hpp"
namespace ARDUINOJSON_NAMESPACE {
// _begin _end
// v v
// +-------------+--------------+-----------+
// | strings... | (free) | ...slots |
// +-------------+--------------+-----------+
// ^ ^
// _left _right
namespace ArduinoJson {
namespace Internals {
// Handle the memory management (done in derived classes) and calls the parser.
// This abstract class is implemented by StaticMemoryPool which implements a
// fixed memory allocation.
class MemoryPool {
public:
// Allocates n bytes in the MemoryPool.
// Return a pointer to the allocated memory or NULL if allocation fails.
virtual void *alloc(size_t size) = 0;
protected:
// CAUTION: NO VIRTUAL DESTRUCTOR!
// If we add a virtual constructor the Arduino compiler will add malloc()
// and free() to the binary, adding 706 useless bytes.
~MemoryPool() {}
// Preserve aligment if necessary
static FORCE_INLINE size_t round_size_up(size_t bytes) {
#if ARDUINOJSON_ENABLE_ALIGNMENT
const size_t x = sizeof(void *) - 1;
return (bytes + x) & ~x;
#else
return bytes;
#endif
MemoryPool(char* buf, size_t capa)
: _begin(buf),
_left(buf),
_right(buf ? buf + capa : 0),
_end(buf ? buf + capa : 0) {
ARDUINOJSON_ASSERT(isAligned(_begin));
ARDUINOJSON_ASSERT(isAligned(_right));
ARDUINOJSON_ASSERT(isAligned(_end));
}
void* buffer() {
return _begin;
}
// Gets the capacity of the memoryPool in bytes
size_t capacity() const {
return size_t(_end - _begin);
}
size_t size() const {
return size_t(_left - _begin + _end - _right);
}
VariantSlot* allocVariant() {
return allocRight<VariantSlot>();
}
char* allocFrozenString(size_t n) {
if (!canAlloc(n)) return 0;
char* s = _left;
_left += n;
checkInvariants();
return s;
}
StringSlot allocExpandableString() {
StringSlot s;
s.value = _left;
s.size = size_t(_right - _left);
_left = _right;
checkInvariants();
return s;
}
void freezeString(StringSlot& s, size_t newSize) {
_left -= (s.size - newSize);
s.size = newSize;
checkInvariants();
}
void clear() {
_left = _begin;
_right = _end;
}
bool canAlloc(size_t bytes) const {
return _left + bytes <= _right;
}
bool owns(void* p) const {
return _begin <= p && p < _end;
}
template <typename T>
T* allocRight() {
return reinterpret_cast<T*>(allocRight(sizeof(T)));
}
char* allocRight(size_t bytes) {
if (!canAlloc(bytes)) return 0;
_right -= bytes;
return _right;
}
// Workaround for missing placement new
void* operator new(size_t, void* p) {
return p;
}
private:
StringSlot* allocStringSlot() {
return allocRight<StringSlot>();
}
void checkInvariants() {
ARDUINOJSON_ASSERT(_begin <= _left);
ARDUINOJSON_ASSERT(_left <= _right);
ARDUINOJSON_ASSERT(_right <= _end);
ARDUINOJSON_ASSERT(isAligned(_right));
}
char *_begin, *_left, *_right, *_end;
};
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,129 +0,0 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// MIT License
#pragma once
#include "../Polyfills/mpl/max.hpp"
#include "MemoryPool.hpp"
namespace ArduinoJson {
namespace Internals {
class StaticMemoryPoolBase : public MemoryPool {
public:
class String {
public:
String(StaticMemoryPoolBase* parent) : _parent(parent) {
_start = parent->_buffer + parent->_size;
}
void append(char c) {
if (_parent->canAlloc(1)) {
char* last = static_cast<char*>(_parent->doAlloc(1));
*last = c;
}
}
const char* c_str() const {
if (_parent->canAlloc(1)) {
char* last = static_cast<char*>(_parent->doAlloc(1));
*last = '\0';
return _start;
} else {
return NULL;
}
}
private:
StaticMemoryPoolBase* _parent;
char* _start;
};
StaticMemoryPoolBase(char* memoryPool, size_t capa)
: _buffer(memoryPool), _capacity(capa), _size(0) {}
// Gets the capacity of the memoryPool in bytes
size_t capacity() const {
return _capacity;
}
// Gets the current usage of the memoryPool in bytes
size_t size() const {
return _size;
}
// Allocates the specified amount of bytes in the memoryPool
virtual void* alloc(size_t bytes) {
alignNextAlloc();
if (!canAlloc(bytes)) return NULL;
return doAlloc(bytes);
}
// Resets the memoryPool.
// USE WITH CAUTION: this invalidates all previously allocated data
void clear() {
_size = 0;
}
String startString() {
return String(this);
}
protected:
~StaticMemoryPoolBase() {}
private:
void alignNextAlloc() {
_size = round_size_up(_size);
}
bool canAlloc(size_t bytes) const {
return _size + bytes <= _capacity;
}
void* doAlloc(size_t bytes) {
void* p = &_buffer[_size];
_size += bytes;
return p;
}
char* _buffer;
size_t _capacity;
size_t _size;
};
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic push
#endif
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#endif
// Implements a MemoryPool with fixed memory allocation.
// The template paramenter CAPACITY specifies the capacity of the memoryPool in
// bytes.
template <size_t CAPACITY>
class StaticMemoryPool : public StaticMemoryPoolBase {
static const size_t ACTUAL_CAPACITY = Max<1, CAPACITY>::value;
public:
explicit StaticMemoryPool()
: StaticMemoryPoolBase(_buffer, ACTUAL_CAPACITY) {}
private:
char _buffer[ACTUAL_CAPACITY];
};
} // namespace Internals
} // namespace ArduinoJson
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
#pragma GCC diagnostic pop
#endif
#endif

View File

@ -0,0 +1,50 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "MemoryPool.hpp"
namespace ARDUINOJSON_NAMESPACE {
class StringBuilder {
public:
explicit StringBuilder(MemoryPool* parent) : _parent(parent), _size(0) {
_slot = _parent->allocExpandableString();
}
void append(const char* s) {
while (*s) append(*s++);
}
void append(const char* s, size_t n) {
while (n-- > 0) append(*s++);
}
void append(char c) {
if (!_slot.value) return;
if (_size >= _slot.size) {
_slot.value = 0;
return;
}
_slot.value[_size++] = c;
}
char* complete() {
append('\0');
if (_slot.value) {
_parent->freezeString(_slot, _size);
}
return _slot.value;
}
private:
MemoryPool* _parent;
size_t _size;
StringSlot _slot;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -0,0 +1,18 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include <stddef.h> // for size_t
#include "../Configuration.hpp"
#define JSON_STRING_SIZE(SIZE) (SIZE)
namespace ARDUINOJSON_NAMESPACE {
struct StringSlot {
char *value;
size_t size;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,14 +1,13 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "Strings/StringTypes.hpp"
#include "../Strings/StringAdapters.hpp"
namespace ArduinoJson {
namespace ARDUINOJSON_NAMESPACE {
namespace Internals {
// A special type of data that can be used to insert pregenerated JSON portions.
template <typename T>
class SerializedValue {
@ -51,20 +50,19 @@ class SerializedValue<TChar*> {
TChar* _data;
size_t _size;
};
} // namespace Internals
template <typename T>
inline Internals::SerializedValue<T> serialized(T str) {
return Internals::SerializedValue<T>(str);
inline SerializedValue<T> serialized(T str) {
return SerializedValue<T>(str);
}
template <typename TChar>
inline Internals::SerializedValue<TChar*> serialized(TChar* p) {
return Internals::SerializedValue<TChar*>(p, Internals::makeString(p).size());
inline SerializedValue<TChar*> serialized(TChar* p) {
return SerializedValue<TChar*>(p, adaptString(p).size());
}
template <typename TChar>
inline Internals::SerializedValue<TChar*> serialized(TChar* p, size_t n) {
return Internals::SerializedValue<TChar*>(p, n);
inline SerializedValue<TChar*> serialized(TChar* p, size_t n) {
return SerializedValue<TChar*>(p, n);
}
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

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

View File

@ -1,40 +1,43 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../Deserialization/deserialize.hpp"
#include "../JsonVariant.hpp"
#include "../Memory/MemoryPool.hpp"
#include "../Polyfills/type_traits.hpp"
#include "./endianess.hpp"
#include "./ieee754.hpp"
#include "../Variant/VariantData.hpp"
#include "endianess.hpp"
#include "ieee754.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename TReader, typename TStringStorage>
class MsgPackDeserializer {
typedef typename remove_reference<TStringStorage>::type::StringBuilder
StringBuilder;
public:
MsgPackDeserializer(MemoryPool &memoryPool, TReader reader,
MsgPackDeserializer(MemoryPool &pool, TReader reader,
TStringStorage stringStorage, uint8_t nestingLimit)
: _memoryPool(&memoryPool),
: _pool(&pool),
_reader(reader),
_stringStorage(stringStorage),
_nestingLimit(nestingLimit) {}
DeserializationError parse(JsonVariant variant) {
DeserializationError parse(VariantData &variant) {
uint8_t code;
if (!readByte(code)) return DeserializationError::IncompleteInput;
if ((code & 0x80) == 0) {
variant.set(code);
variant.setUnsignedInteger(code);
return DeserializationError::Ok;
}
if ((code & 0xe0) == 0xe0) {
variant.set(static_cast<int8_t>(code));
// TODO: add setNegativeInteger()
variant.setSignedInteger(static_cast<int8_t>(code));
return DeserializationError::Ok;
}
@ -42,9 +45,13 @@ class MsgPackDeserializer {
return readString(variant, code & 0x1f);
}
if ((code & 0xf0) == 0x90) return readArray(variant, code & 0x0F);
if ((code & 0xf0) == 0x90) {
return readArray(variant.toArray(), code & 0x0F);
}
if ((code & 0xf0) == 0x80) return readObject(variant, code & 0x0F);
if ((code & 0xf0) == 0x80) {
return readObject(variant.toObject(), code & 0x0F);
}
switch (code) {
case 0xc0:
@ -52,11 +59,11 @@ class MsgPackDeserializer {
return DeserializationError::Ok;
case 0xc2:
variant.set(false);
variant.setBoolean(false);
return DeserializationError::Ok;
case 0xc3:
variant.set(true);
variant.setBoolean(true);
return DeserializationError::Ok;
case 0xcc:
@ -69,7 +76,7 @@ class MsgPackDeserializer {
return readInteger<uint32_t>(variant);
case 0xcf:
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
#if ARDUINOJSON_USE_LONG_LONG
return readInteger<uint64_t>(variant);
#else
readInteger<uint32_t>();
@ -86,7 +93,7 @@ class MsgPackDeserializer {
return readInteger<int32_t>(variant);
case 0xd3:
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
#if ARDUINOJSON_USE_LONG_LONG
return readInteger<int64_t>(variant);
#else
if (!skip(4)) return DeserializationError::IncompleteInput;
@ -109,16 +116,16 @@ class MsgPackDeserializer {
return readString<uint32_t>(variant);
case 0xdc:
return readArray<uint16_t>(variant);
return readArray<uint16_t>(variant.toArray());
case 0xdd:
return readArray<uint32_t>(variant);
return readArray<uint32_t>(variant.toArray());
case 0xde:
return readObject<uint16_t>(variant);
return readObject<uint16_t>(variant.toObject());
case 0xdf:
return readObject<uint32_t>(variant);
return readObject<uint32_t>(variant.toObject());
default:
return DeserializationError::NotSupported;
@ -171,88 +178,94 @@ class MsgPackDeserializer {
}
template <typename T>
DeserializationError readInteger(JsonVariant variant) {
DeserializationError readInteger(VariantData &variant) {
T value;
if (!readInteger(value)) return DeserializationError::IncompleteInput;
variant.set(value);
variant.setInteger(value);
return DeserializationError::Ok;
}
template <typename T>
typename enable_if<sizeof(T) == 4, DeserializationError>::type readFloat(
JsonVariant variant) {
VariantData &variant) {
T value;
if (!readBytes(value)) return DeserializationError::IncompleteInput;
fixEndianess(value);
variant.set(value);
variant.setFloat(value);
return DeserializationError::Ok;
}
template <typename T>
typename enable_if<sizeof(T) == 8, DeserializationError>::type readDouble(
JsonVariant variant) {
VariantData &variant) {
T value;
if (!readBytes(value)) return DeserializationError::IncompleteInput;
fixEndianess(value);
variant.set(value);
variant.setFloat(value);
return DeserializationError::Ok;
}
template <typename T>
typename enable_if<sizeof(T) == 4, DeserializationError>::type readDouble(
JsonVariant variant) {
VariantData &variant) {
uint8_t i[8]; // input is 8 bytes
T value; // output is 4 bytes
uint8_t *o = reinterpret_cast<uint8_t *>(&value);
if (!readBytes(i, 8)) return DeserializationError::IncompleteInput;
doubleToFloat(i, o);
fixEndianess(value);
variant.set(value);
variant.setFloat(value);
return DeserializationError::Ok;
}
template <typename T>
DeserializationError readString(JsonVariant variant) {
DeserializationError readString(VariantData &variant) {
T size;
if (!readInteger(size)) return DeserializationError::IncompleteInput;
return readString(variant, size);
}
DeserializationError readString(JsonVariant variant, size_t n) {
typename remove_reference<TStringStorage>::type::String str =
_stringStorage.startString();
template <typename T>
DeserializationError readString(const char *&str) {
T size;
if (!readInteger(size)) return DeserializationError::IncompleteInput;
return readString(str, size);
}
DeserializationError readString(VariantData &variant, size_t n) {
const char *s;
DeserializationError err = readString(s, n);
if (!err) variant.setOwnedString(make_not_null(s));
return err;
}
DeserializationError readString(const char *&result, size_t n) {
StringBuilder builder = _stringStorage.startString();
for (; n; --n) {
uint8_t c;
if (!readBytes(c)) return DeserializationError::IncompleteInput;
str.append(static_cast<char>(c));
builder.append(static_cast<char>(c));
}
const char *s = str.c_str();
if (s == NULL) return DeserializationError::NoMemory;
variant.set(s);
result = builder.complete();
if (!result) return DeserializationError::NoMemory;
return DeserializationError::Ok;
}
template <typename TSize>
DeserializationError readArray(JsonVariant variant) {
DeserializationError readArray(CollectionData &array) {
TSize size;
if (!readInteger(size)) return DeserializationError::IncompleteInput;
return readArray(variant, size);
return readArray(array, size);
}
DeserializationError readArray(JsonVariant variant, size_t n) {
JsonArray array = variant.to<JsonArray>();
if (array.isNull()) return DeserializationError::NoMemory;
return readArray(array, n);
}
DeserializationError readArray(JsonArray array, size_t n) {
DeserializationError readArray(CollectionData &array, size_t n) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
--_nestingLimit;
for (; n; --n) {
JsonVariant value = array.add();
if (value.isInvalid()) return DeserializationError::NoMemory;
VariantData *value = array.add(_pool);
if (!value) return DeserializationError::NoMemory;
DeserializationError err = parse(value);
DeserializationError err = parse(*value);
if (err) return err;
}
++_nestingLimit;
@ -260,68 +273,83 @@ class MsgPackDeserializer {
}
template <typename TSize>
DeserializationError readObject(JsonVariant variant) {
DeserializationError readObject(CollectionData &object) {
TSize size;
if (!readInteger(size)) return DeserializationError::IncompleteInput;
return readObject(variant, size);
return readObject(object, size);
}
DeserializationError readObject(JsonVariant variant, size_t n) {
JsonObject object = variant.to<JsonObject>();
if (object.isNull()) return DeserializationError::NoMemory;
return readObject(object, n);
}
DeserializationError readObject(JsonObject object, size_t n) {
DeserializationError readObject(CollectionData &object, size_t n) {
if (_nestingLimit == 0) return DeserializationError::TooDeep;
--_nestingLimit;
for (; n; --n) {
JsonVariantData keyData;
JsonVariant key(_memoryPool, &keyData);
DeserializationError err = parse(key);
VariantSlot *slot = object.addSlot(_pool);
if (!slot) return DeserializationError::NoMemory;
const char *key;
DeserializationError err = parseKey(key);
if (err) return err;
if (!keyData.isString()) return DeserializationError::NotSupported;
slot->setOwnedKey(make_not_null(key));
JsonVariant value = object.set(keyData.asString());
if (value.isInvalid()) return DeserializationError::NoMemory;
err = parse(value);
err = parse(*slot->data());
if (err) return err;
}
++_nestingLimit;
return DeserializationError::Ok;
}
MemoryPool *_memoryPool;
DeserializationError parseKey(const char *&key) {
uint8_t code;
if (!readByte(code)) return DeserializationError::IncompleteInput;
if ((code & 0xe0) == 0xa0) return readString(key, code & 0x1f);
switch (code) {
case 0xd9:
return readString<uint8_t>(key);
case 0xda:
return readString<uint16_t>(key);
case 0xdb:
return readString<uint32_t>(key);
default:
return DeserializationError::NotSupported;
}
}
MemoryPool *_pool;
TReader _reader;
TStringStorage _stringStorage;
uint8_t _nestingLimit;
};
} // namespace Internals
template <typename TDocument, typename TInput>
DeserializationError deserializeMsgPack(TDocument &doc, const TInput &input) {
using namespace Internals;
return deserialize<MsgPackDeserializer>(doc, input);
template <typename TInput>
DeserializationError deserializeMsgPack(
JsonDocument &doc, const TInput &input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeMsgPack(TDocument &doc, TInput *input) {
using namespace Internals;
return deserialize<MsgPackDeserializer>(doc, input);
template <typename TInput>
DeserializationError deserializeMsgPack(
JsonDocument &doc, TInput *input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeMsgPack(TDocument &doc, TInput *input,
size_t inputSize) {
using namespace Internals;
return deserialize<MsgPackDeserializer>(doc, input, inputSize);
template <typename TInput>
DeserializationError deserializeMsgPack(
JsonDocument &doc, TInput *input, size_t inputSize,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit);
}
template <typename TDocument, typename TInput>
DeserializationError deserializeMsgPack(TDocument &doc, TInput &input) {
using namespace Internals;
return deserialize<MsgPackDeserializer>(doc, input);
template <typename TInput>
DeserializationError deserializeMsgPack(
JsonDocument &doc, TInput &input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit);
}
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,17 +1,16 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
#include "../JsonVariant.hpp"
#include "../Polyfills/type_traits.hpp"
#include "../Serialization/measure.hpp"
#include "../Serialization/serialize.hpp"
#include "./endianess.hpp"
#include "../Variant/VariantData.hpp"
#include "endianess.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
template <typename TWriter>
class MsgPackSerializer {
@ -36,7 +35,7 @@ class MsgPackSerializer {
}
}
void visitArray(JsonArray array) {
void visitArray(const CollectionData& array) {
size_t n = array.size();
if (n < 0x10) {
writeByte(uint8_t(0x90 + array.size()));
@ -47,12 +46,12 @@ class MsgPackSerializer {
writeByte(0xDD);
writeInteger(uint32_t(n));
}
for (JsonArray::iterator it = array.begin(); it != array.end(); ++it) {
it->accept(*this);
for (VariantSlot* slot = array.head(); slot; slot = slot->next()) {
slot->data()->accept(*this);
}
}
void visitObject(JsonObject object) {
void visitObject(const CollectionData& object) {
size_t n = object.size();
if (n < 0x10) {
writeByte(uint8_t(0x80 + n));
@ -63,9 +62,9 @@ class MsgPackSerializer {
writeByte(0xDF);
writeInteger(uint32_t(n));
}
for (JsonObject::iterator it = object.begin(); it != object.end(); ++it) {
visitString(it->key());
it->value().accept(*this);
for (VariantSlot* slot = object.head(); slot; slot = slot->next()) {
visitString(slot->key());
slot->data()->accept(*this);
}
}
@ -93,8 +92,8 @@ class MsgPackSerializer {
writeBytes(reinterpret_cast<const uint8_t*>(data), size);
}
void visitNegativeInteger(JsonUInt value) {
JsonUInt negated = JsonUInt(~value + 1);
void visitNegativeInteger(UInt value) {
UInt negated = UInt(~value + 1);
if (value <= 0x20) {
writeInteger(int8_t(negated));
} else if (value <= 0x80) {
@ -107,7 +106,7 @@ class MsgPackSerializer {
writeByte(0xD2);
writeInteger(int32_t(negated));
}
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
#if ARDUINOJSON_USE_LONG_LONG
else {
writeByte(0xD3);
writeInteger(int64_t(negated));
@ -115,7 +114,7 @@ class MsgPackSerializer {
#endif
}
void visitPositiveInteger(JsonUInt value) {
void visitPositiveInteger(UInt value) {
if (value <= 0x7F) {
writeInteger(uint8_t(value));
} else if (value <= 0xFF) {
@ -128,7 +127,7 @@ class MsgPackSerializer {
writeByte(0xCE);
writeInteger(uint32_t(value));
}
#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64
#if ARDUINOJSON_USE_LONG_LONG
else {
writeByte(0xCF);
writeInteger(uint64_t(value));
@ -166,25 +165,21 @@ class MsgPackSerializer {
TWriter* _writer;
size_t _bytesWritten;
};
} // namespace Internals
template <typename TSource, typename TDestination>
inline size_t serializeMsgPack(const TSource& source, TDestination& output) {
using namespace Internals;
return serialize<MsgPackSerializer>(source, output);
}
template <typename TSource, typename TDestination>
inline size_t serializeMsgPack(const TSource& source, TDestination* output,
size_t size) {
using namespace Internals;
return serialize<MsgPackSerializer>(source, output, size);
}
template <typename TSource>
inline size_t measureMsgPack(const TSource& source) {
using namespace Internals;
return measure<MsgPackSerializer>(source);
}
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,5 +1,5 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
@ -7,8 +7,7 @@
#include "../Polyfills/type_traits.hpp"
#include "../Polyfills/utility.hpp"
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
inline void fixEndianess(uint8_t* p, integral_constant<size_t, 8>) {
swap(p[0], p[7]);
@ -36,5 +35,4 @@ inline void fixEndianess(T& value) {
#endif
}
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

View File

@ -1,11 +1,10 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2018
// Copyright Benoit Blanchon 2014-2019
// MIT License
#pragma once
namespace ArduinoJson {
namespace Internals {
namespace ARDUINOJSON_NAMESPACE {
inline void doubleToFloat(const uint8_t d[8], uint8_t f[4]) {
f[0] = uint8_t((d[0] & 0xC0) | (d[0] << 3 & 0x3f) | (d[1] >> 5));
@ -14,5 +13,4 @@ inline void doubleToFloat(const uint8_t d[8], uint8_t f[4]) {
f[3] = uint8_t((d[3] << 3) | (d[4] >> 5));
}
} // namespace Internals
} // namespace ArduinoJson
} // namespace ARDUINOJSON_NAMESPACE

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