mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 07:49:52 +03:00
upgrade ArduinoJson to 6.21.2
This commit is contained in:
@@ -1,6 +1,19 @@
|
|||||||
ArduinoJson: change log
|
ArduinoJson: change log
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
|
v6.21.2 (2023-04-12)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Fix compatibility with the Zephyr Project (issue #1905)
|
||||||
|
* Allow using PROGMEM outside of Arduino (issue #1903)
|
||||||
|
* Set default for `ARDUINOJSON_ENABLE_PROGMEM` to `1` on AVR
|
||||||
|
|
||||||
|
v6.21.1 (2023-03-27)
|
||||||
|
-------
|
||||||
|
|
||||||
|
* Double speed of `DynamicJsonDocument::garbageCollect()`
|
||||||
|
* Fix compatibility with GCC 5.2 (issue #1897)
|
||||||
|
|
||||||
v6.21.0 (2023-03-14)
|
v6.21.0 (2023-03-14)
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
|||||||
161
lib/ArduinoJson/README.md
Normal file
161
lib/ArduinoJson/README.md
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
<p align="center">
|
||||||
|
<a href="https://arduinojson.org/"><img alt="ArduinoJson" src="https://arduinojson.org/images/logo.svg" width="200" /></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A6.x)
|
||||||
|
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
|
||||||
|
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson)
|
||||||
|
[](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x)
|
||||||
|
[](https://www.ardu-badge.com/ArduinoJson/6.21.2)
|
||||||
|
[](https://registry.platformio.org/packages/libraries/bblanchon/ArduinoJson?version=6.21.2)
|
||||||
|
[](https://components.espressif.com/components/bblanchon/arduinojson)
|
||||||
|
[](https://github.com/bblanchon/ArduinoJson/stargazers)
|
||||||
|
[](https://github.com/sponsors/bblanchon)
|
||||||
|
|
||||||
|
ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
* [JSON deserialization](https://arduinojson.org/v6/api/json/deserializejson/)
|
||||||
|
* [Optionally decodes UTF-16 escape sequences to UTF-8](https://arduinojson.org/v6/api/config/decode_unicode/)
|
||||||
|
* [Optionally stores links to the input buffer (zero-copy)](https://arduinojson.org/v6/api/json/deserializejson/)
|
||||||
|
* [Optionally supports comments in the input](https://arduinojson.org/v6/api/config/enable_comments/)
|
||||||
|
* [Optionally filters the input to keep only desired values](https://arduinojson.org/v6/api/json/deserializejson/#filtering)
|
||||||
|
* Supports single quotes as a string delimiter
|
||||||
|
* Compatible with [NDJSON](http://ndjson.org/) and [JSON Lines](https://jsonlines.org/)
|
||||||
|
* [JSON serialization](https://arduinojson.org/v6/api/json/serializejson/)
|
||||||
|
* [Can write to a buffer or a stream](https://arduinojson.org/v6/api/json/serializejson/)
|
||||||
|
* [Optionally indents the document (prettified JSON)](https://arduinojson.org/v6/api/json/serializejsonpretty/)
|
||||||
|
* [MessagePack serialization](https://arduinojson.org/v6/api/msgpack/serializemsgpack/)
|
||||||
|
* [MessagePack deserialization](https://arduinojson.org/v6/api/msgpack/deserializemsgpack/)
|
||||||
|
* Efficient
|
||||||
|
* [Twice smaller than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/)
|
||||||
|
* [Almost 10% faster than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/)
|
||||||
|
* [Consumes roughly 10% less RAM than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/)
|
||||||
|
* [Fixed memory allocation, no heap fragmentation](https://arduinojson.org/v6/api/jsondocument/)
|
||||||
|
* [Optionally works without heap memory (zero malloc)](https://arduinojson.org/v6/api/staticjsondocument/)
|
||||||
|
* [Deduplicates strings](https://arduinojson.org/news/2020/08/01/version-6-16-0/)
|
||||||
|
* Versatile
|
||||||
|
* Supports [custom allocators (to use external RAM chip, for example)](https://arduinojson.org/v6/how-to/use-external-ram-on-esp32/)
|
||||||
|
* Supports [`String`](https://arduinojson.org/v6/api/config/enable_arduino_string/), [`std::string`](https://arduinojson.org/v6/api/config/enable_std_string/), and [`std::string_view`](https://arduinojson.org/v6/api/config/enable_string_view/)
|
||||||
|
* Supports [`Stream`](https://arduinojson.org/v6/api/config/enable_arduino_stream/) and [`std::istream`/`std::ostream`](https://arduinojson.org/v6/api/config/enable_std_stream/)
|
||||||
|
* Supports [Flash strings](https://arduinojson.org/v6/api/config/enable_progmem/)
|
||||||
|
* Supports [custom readers](https://arduinojson.org/v6/api/json/deserializejson/#custom-reader) and [custom writers](https://arduinojson.org/v6/api/json/serializejson/#custom-writer)
|
||||||
|
* Supports [custom converters](https://arduinojson.org/news/2021/05/04/version-6-18-0/)
|
||||||
|
* Portable
|
||||||
|
* Usable on any C++ project (not limited to Arduino)
|
||||||
|
* Compatible with C++11, C++14 and C++17
|
||||||
|
* Support for C++98/C++03 available on [ArduinoJson 6.20.x](https://github.com/bblanchon/ArduinoJson/tree/6.20.x)
|
||||||
|
* Zero warnings with `-Wall -Wextra -pedantic` and `/W4`
|
||||||
|
* [Header-only library](https://en.wikipedia.org/wiki/Header-only)
|
||||||
|
* Works with virtually any board
|
||||||
|
* Arduino boards: [Uno](https://amzn.to/38aL2ik), [Due](https://amzn.to/36YkWi2), [Micro](https://amzn.to/35WkdwG), [Nano](https://amzn.to/2QTvwRX), [Mega](https://amzn.to/36XWhuf), [Yun](https://amzn.to/30odURc), [Leonardo](https://amzn.to/36XWjlR)...
|
||||||
|
* Espressif chips: [ESP8266](https://amzn.to/36YluV8), [ESP32](https://amzn.to/2G4pRCB)
|
||||||
|
* Lolin (WeMos) boards: [D1 mini](https://amzn.to/2QUpz7q), [D1 Mini Pro](https://amzn.to/36UsGSs)...
|
||||||
|
* Teensy boards: [4.0](https://amzn.to/30ljXGq), [3.2](https://amzn.to/2FT0EuC), [2.0](https://amzn.to/2QXUMXj)
|
||||||
|
* Particle boards: [Argon](https://amzn.to/2FQHa9X), [Boron](https://amzn.to/36WgLUd), [Electron](https://amzn.to/30vEc4k), [Photon](https://amzn.to/387F9Cd)...
|
||||||
|
* Texas Instruments boards: [MSP430](https://amzn.to/30nJWgg)...
|
||||||
|
* Soft cores: [Nios II](https://en.wikipedia.org/wiki/Nios_II)...
|
||||||
|
* Tested on all major development environments
|
||||||
|
* [Arduino IDE](https://www.arduino.cc/en/Main/Software)
|
||||||
|
* [Atmel Studio](http://www.atmel.com/microsite/atmel-studio/)
|
||||||
|
* [Atollic TrueSTUDIO](https://atollic.com/truestudio/)
|
||||||
|
* [Energia](http://energia.nu/)
|
||||||
|
* [IAR Embedded Workbench](https://www.iar.com/iar-embedded-workbench/)
|
||||||
|
* [Keil uVision](http://www.keil.com/)
|
||||||
|
* [MPLAB X IDE](http://www.microchip.com/mplab/mplab-x-ide)
|
||||||
|
* [Particle](https://www.particle.io/)
|
||||||
|
* [PlatformIO](http://platformio.org/)
|
||||||
|
* [Sloeber plugin for Eclipse](https://eclipse.baeyens.it/)
|
||||||
|
* [Visual Micro](http://www.visualmicro.com/)
|
||||||
|
* [Visual Studio](https://www.visualstudio.com/)
|
||||||
|
* [Even works with online compilers like wandbox.org](https://wandbox.org/permlink/RlZSKy17DjJ6HcdN)
|
||||||
|
* [CMake friendly](https://arduinojson.org/v6/how-to/use-arduinojson-with-cmake/)
|
||||||
|
* Well designed
|
||||||
|
* [Elegant API](http://arduinojson.org/v6/example/)
|
||||||
|
* [Thread-safe](https://en.wikipedia.org/wiki/Thread_safety)
|
||||||
|
* Self-contained (no external dependency)
|
||||||
|
* `const` friendly
|
||||||
|
* [`for` friendly](https://arduinojson.org/v6/api/jsonobject/begin_end/)
|
||||||
|
* [TMP friendly](https://en.wikipedia.org/wiki/Template_metaprogramming)
|
||||||
|
* Handles [integer overflows](https://arduinojson.org/v6/api/jsonvariant/as/#integer-overflows)
|
||||||
|
* Well tested
|
||||||
|
* [Unit test coverage close to 100%](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x)
|
||||||
|
* Continuously tested on
|
||||||
|
* [Visual Studio 2017, 2019, 2022](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
|
||||||
|
* [GCC 5, 6, 7, 8, 9, 10, 11](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22)
|
||||||
|
* [Clang 3.8, 3.9, 4.0, 5.0, 6.0, 7, 8, 9, 10](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22)
|
||||||
|
* [Continuously fuzzed with Google OSS Fuzz](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson)
|
||||||
|
* Passes all default checks of [clang-tidy](https://releases.llvm.org/10.0.0/tools/clang/tools/extra/docs/clang-tidy/)
|
||||||
|
* Well documented
|
||||||
|
* [Tutorials](https://arduinojson.org/v6/doc/deserialization/)
|
||||||
|
* [Examples](https://arduinojson.org/v6/example/)
|
||||||
|
* [How-tos](https://arduinojson.org/v6/example/)
|
||||||
|
* [FAQ](https://arduinojson.org/v6/faq/)
|
||||||
|
* [Troubleshooter](https://arduinojson.org/v6/troubleshooter/)
|
||||||
|
* [Book](https://arduinojson.org/book/)
|
||||||
|
* [Changelog](CHANGELOG.md)
|
||||||
|
* Vibrant user community
|
||||||
|
* Most popular of all Arduino libraries on [GitHub](https://github.com/search?o=desc&q=arduino+library&s=stars&type=Repositories)
|
||||||
|
* [Used in hundreds of projects](https://www.hackster.io/search?i=projects&q=arduinojson)
|
||||||
|
* [Responsive support](https://github.com/bblanchon/ArduinoJson/issues?q=is%3Aissue+is%3Aclosed)
|
||||||
|
|
||||||
|
## Quickstart
|
||||||
|
|
||||||
|
### Deserialization
|
||||||
|
|
||||||
|
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(1024);
|
||||||
|
deserializeJson(doc, json);
|
||||||
|
|
||||||
|
const char* sensor = doc["sensor"];
|
||||||
|
long time = doc["time"];
|
||||||
|
double latitude = doc["data"][0];
|
||||||
|
double longitude = doc["data"][1];
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [tutorial on arduinojson.org](https://arduinojson.org/v6/doc/deserialization/)
|
||||||
|
|
||||||
|
### Serialization
|
||||||
|
|
||||||
|
Here is a program that generates a JSON document with ArduinoJson:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
DynamicJsonDocument doc(1024);
|
||||||
|
|
||||||
|
doc["sensor"] = "gps";
|
||||||
|
doc["time"] = 1351824120;
|
||||||
|
doc["data"][0] = 48.756080;
|
||||||
|
doc["data"][1] = 2.302038;
|
||||||
|
|
||||||
|
serializeJson(doc, Serial);
|
||||||
|
// This prints:
|
||||||
|
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [tutorial on arduinojson.org](https://arduinojson.org/v6/doc/serialization/)
|
||||||
|
|
||||||
|
## Sponsors
|
||||||
|
|
||||||
|
ArduinoJson is thankful to its sponsors. Please give them a visit; they deserve it!
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a href="https://www.programmingelectronics.com/" rel="sponsored">
|
||||||
|
<img src="https://arduinojson.org/images/2021/10/programmingeleactronicsacademy.png" alt="Programming Electronics Academy" width="200">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://github.com/1technophile" rel="sponsored">
|
||||||
|
<img alt="1technophile" src="https://avatars.githubusercontent.com/u/12672732?s=40&v=4">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
If you run a commercial project that embeds ArduinoJson, think about [sponsoring the library's development](https://github.com/sponsors/bblanchon): it ensures the code that your products rely on stays actively maintained. It can also give your project some exposure to the makers' community.
|
||||||
|
|
||||||
|
If you are an individual user and want to support the development (or give a sign of appreciation), consider purchasing the book [Mastering ArduinoJson](https://arduinojson.org/book/) ❤, or simply [cast a star](https://github.com/bblanchon/ArduinoJson/stargazers) ⭐.
|
||||||
40
lib/ArduinoJson/keywords.txt
Normal file
40
lib/ArduinoJson/keywords.txt
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# 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
|
||||||
|
measureJson KEYWORD2
|
||||||
|
measureJsonPretty KEYWORD2
|
||||||
|
measureMsgPack KEYWORD2
|
||||||
|
|
||||||
|
# Methods
|
||||||
|
add KEYWORD2
|
||||||
|
as KEYWORD2
|
||||||
|
createNestedArray KEYWORD2
|
||||||
|
createNestedObject KEYWORD2
|
||||||
|
get KEYWORD2
|
||||||
|
set KEYWORD2
|
||||||
|
to KEYWORD2
|
||||||
|
|
||||||
|
# Type names
|
||||||
|
DeserializationError KEYWORD1 DATA_TYPE
|
||||||
|
DynamicJsonDocument KEYWORD1 DATA_TYPE
|
||||||
|
JsonArray KEYWORD1 DATA_TYPE
|
||||||
|
JsonArrayConst KEYWORD1 DATA_TYPE
|
||||||
|
JsonDocument 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
|
||||||
11
lib/ArduinoJson/library.properties
Normal file
11
lib/ArduinoJson/library.properties
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
name=ArduinoJson
|
||||||
|
version=6.21.2
|
||||||
|
author=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||||
|
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||||
|
sentence=A simple and efficient JSON library for embedded C++.
|
||||||
|
paragraph=ArduinoJson supports ✔ serialization, ✔ deserialization, ✔ MessagePack, ✔ fixed allocation, ✔ zero-copy, ✔ streams, ✔ filtering, and more. It is the most popular Arduino library on GitHub ❤❤❤❤❤. Check out arduinojson.org for a comprehensive documentation.
|
||||||
|
category=Data Processing
|
||||||
|
url=https://arduinojson.org/?utm_source=meta&utm_medium=library.properties
|
||||||
|
architectures=*
|
||||||
|
repository=https://github.com/bblanchon/ArduinoJson.git
|
||||||
|
license=MIT
|
||||||
@@ -13,7 +13,8 @@
|
|||||||
// Include Arduino.h before stdlib.h to avoid conflict with atexit()
|
// Include Arduino.h before stdlib.h to avoid conflict with atexit()
|
||||||
// https://github.com/bblanchon/ArduinoJson/pull/1693#issuecomment-1001060240
|
// https://github.com/bblanchon/ArduinoJson/pull/1693#issuecomment-1001060240
|
||||||
#if ARDUINOJSON_ENABLE_ARDUINO_STRING || ARDUINOJSON_ENABLE_ARDUINO_STREAM || \
|
#if ARDUINOJSON_ENABLE_ARDUINO_STRING || ARDUINOJSON_ENABLE_ARDUINO_STREAM || \
|
||||||
ARDUINOJSON_ENABLE_ARDUINO_PRINT || ARDUINOJSON_ENABLE_PROGMEM
|
ARDUINOJSON_ENABLE_ARDUINO_PRINT || \
|
||||||
|
(ARDUINOJSON_ENABLE_PROGMEM && defined(ARDUINO))
|
||||||
# include <Arduino.h>
|
# include <Arduino.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ class ElementProxy : public VariantRefBase<ElementProxy<TUpstream>>,
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
ElementProxy(TUpstream upstream, size_t index)
|
ElementProxy(TUpstream upstream, size_t index)
|
||||||
: _upstream(upstream), _index(index) {}
|
: upstream_(upstream), index_(index) {}
|
||||||
|
|
||||||
ElementProxy(const ElementProxy& src)
|
ElementProxy(const ElementProxy& src)
|
||||||
: _upstream(src._upstream), _index(src._index) {}
|
: upstream_(src.upstream_), index_(src.index_) {}
|
||||||
|
|
||||||
FORCE_INLINE ElementProxy& operator=(const ElementProxy& src) {
|
FORCE_INLINE ElementProxy& operator=(const ElementProxy& src) {
|
||||||
this->set(src);
|
this->set(src);
|
||||||
@@ -41,20 +41,20 @@ class ElementProxy : public VariantRefBase<ElementProxy<TUpstream>>,
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
FORCE_INLINE MemoryPool* getPool() const {
|
FORCE_INLINE MemoryPool* getPool() const {
|
||||||
return VariantAttorney::getPool(_upstream);
|
return VariantAttorney::getPool(upstream_);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE VariantData* getData() const {
|
FORCE_INLINE VariantData* getData() const {
|
||||||
return variantGetElement(VariantAttorney::getData(_upstream), _index);
|
return variantGetElement(VariantAttorney::getData(upstream_), index_);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE VariantData* getOrCreateData() const {
|
FORCE_INLINE VariantData* getOrCreateData() const {
|
||||||
return variantGetOrAddElement(VariantAttorney::getOrCreateData(_upstream),
|
return variantGetOrAddElement(VariantAttorney::getOrCreateData(upstream_),
|
||||||
_index, VariantAttorney::getPool(_upstream));
|
index_, VariantAttorney::getPool(upstream_));
|
||||||
}
|
}
|
||||||
|
|
||||||
TUpstream _upstream;
|
TUpstream upstream_;
|
||||||
size_t _index;
|
size_t index_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -20,32 +20,32 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
|
|||||||
typedef JsonArrayIterator iterator;
|
typedef JsonArrayIterator iterator;
|
||||||
|
|
||||||
// Constructs an unbound reference.
|
// Constructs an unbound reference.
|
||||||
FORCE_INLINE JsonArray() : _data(0), _pool(0) {}
|
FORCE_INLINE JsonArray() : data_(0), pool_(0) {}
|
||||||
|
|
||||||
// INTERNAL USE ONLY
|
// INTERNAL USE ONLY
|
||||||
FORCE_INLINE JsonArray(detail::MemoryPool* pool, detail::CollectionData* data)
|
FORCE_INLINE JsonArray(detail::MemoryPool* pool, detail::CollectionData* data)
|
||||||
: _data(data), _pool(pool) {}
|
: data_(data), pool_(pool) {}
|
||||||
|
|
||||||
// Returns a JsonVariant pointing to the array.
|
// Returns a JsonVariant pointing to the array.
|
||||||
// https://arduinojson.org/v6/api/jsonvariant/
|
// https://arduinojson.org/v6/api/jsonvariant/
|
||||||
operator JsonVariant() {
|
operator JsonVariant() {
|
||||||
void* data = _data; // prevent warning cast-align
|
void* data = data_; // prevent warning cast-align
|
||||||
return JsonVariant(_pool, reinterpret_cast<detail::VariantData*>(data));
|
return JsonVariant(pool_, reinterpret_cast<detail::VariantData*>(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a read-only reference to the array.
|
// Returns a read-only reference to the array.
|
||||||
// https://arduinojson.org/v6/api/jsonarrayconst/
|
// https://arduinojson.org/v6/api/jsonarrayconst/
|
||||||
operator JsonArrayConst() const {
|
operator JsonArrayConst() const {
|
||||||
return JsonArrayConst(_data);
|
return JsonArrayConst(data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends a new (null) element to the array.
|
// Appends a new (null) element to the array.
|
||||||
// Returns a reference to the new element.
|
// Returns a reference to the new element.
|
||||||
// https://arduinojson.org/v6/api/jsonarray/add/
|
// https://arduinojson.org/v6/api/jsonarray/add/
|
||||||
JsonVariant add() const {
|
JsonVariant add() const {
|
||||||
if (!_data)
|
if (!data_)
|
||||||
return JsonVariant();
|
return JsonVariant();
|
||||||
return JsonVariant(_pool, _data->addElement(_pool));
|
return JsonVariant(pool_, data_->addElement(pool_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends a value to the array.
|
// Appends a value to the array.
|
||||||
@@ -65,9 +65,9 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
|
|||||||
// Returns an iterator to the first element of the array.
|
// Returns an iterator to the first element of the array.
|
||||||
// https://arduinojson.org/v6/api/jsonarray/begin/
|
// https://arduinojson.org/v6/api/jsonarray/begin/
|
||||||
FORCE_INLINE iterator begin() const {
|
FORCE_INLINE iterator begin() const {
|
||||||
if (!_data)
|
if (!data_)
|
||||||
return iterator();
|
return iterator();
|
||||||
return iterator(_pool, _data->head());
|
return iterator(pool_, data_->head());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an iterator following the last element of the array.
|
// Returns an iterator following the last element of the array.
|
||||||
@@ -79,41 +79,41 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
|
|||||||
// Copies an array.
|
// Copies an array.
|
||||||
// https://arduinojson.org/v6/api/jsonarray/set/
|
// https://arduinojson.org/v6/api/jsonarray/set/
|
||||||
FORCE_INLINE bool set(JsonArrayConst src) const {
|
FORCE_INLINE bool set(JsonArrayConst src) const {
|
||||||
if (!_data || !src._data)
|
if (!data_ || !src.data_)
|
||||||
return false;
|
return false;
|
||||||
return _data->copyFrom(*src._data, _pool);
|
return data_->copyFrom(*src.data_, pool_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compares the content of two arrays.
|
// Compares the content of two arrays.
|
||||||
FORCE_INLINE bool operator==(JsonArray rhs) const {
|
FORCE_INLINE bool operator==(JsonArray rhs) const {
|
||||||
return JsonArrayConst(_data) == JsonArrayConst(rhs._data);
|
return JsonArrayConst(data_) == JsonArrayConst(rhs.data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes the element at the specified iterator.
|
// Removes the element at the specified iterator.
|
||||||
// ⚠️ Doesn't release the memory associated with the removed element.
|
// ⚠️ Doesn't release the memory associated with the removed element.
|
||||||
// https://arduinojson.org/v6/api/jsonarray/remove/
|
// https://arduinojson.org/v6/api/jsonarray/remove/
|
||||||
FORCE_INLINE void remove(iterator it) const {
|
FORCE_INLINE void remove(iterator it) const {
|
||||||
if (!_data)
|
if (!data_)
|
||||||
return;
|
return;
|
||||||
_data->removeSlot(it._slot);
|
data_->removeSlot(it.slot_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes the element at the specified index.
|
// Removes the element at the specified index.
|
||||||
// ⚠️ Doesn't release the memory associated with the removed element.
|
// ⚠️ Doesn't release the memory associated with the removed element.
|
||||||
// https://arduinojson.org/v6/api/jsonarray/remove/
|
// https://arduinojson.org/v6/api/jsonarray/remove/
|
||||||
FORCE_INLINE void remove(size_t index) const {
|
FORCE_INLINE void remove(size_t index) const {
|
||||||
if (!_data)
|
if (!data_)
|
||||||
return;
|
return;
|
||||||
_data->removeElement(index);
|
data_->removeElement(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes all the elements of the array.
|
// Removes all the elements of the array.
|
||||||
// ⚠️ Doesn't release the memory associated with the removed elements.
|
// ⚠️ Doesn't release the memory associated with the removed elements.
|
||||||
// https://arduinojson.org/v6/api/jsonarray/clear/
|
// https://arduinojson.org/v6/api/jsonarray/clear/
|
||||||
void clear() const {
|
void clear() const {
|
||||||
if (!_data)
|
if (!data_)
|
||||||
return;
|
return;
|
||||||
_data->clear();
|
data_->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets or sets the element at the specified index.
|
// Gets or sets the element at the specified index.
|
||||||
@@ -133,54 +133,54 @@ class JsonArray : public detail::VariantOperators<JsonArray> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
operator JsonVariantConst() const {
|
operator JsonVariantConst() const {
|
||||||
return JsonVariantConst(collectionToVariant(_data));
|
return JsonVariantConst(collectionToVariant(data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the reference is unbound.
|
// Returns true if the reference is unbound.
|
||||||
// https://arduinojson.org/v6/api/jsonarray/isnull/
|
// https://arduinojson.org/v6/api/jsonarray/isnull/
|
||||||
FORCE_INLINE bool isNull() const {
|
FORCE_INLINE bool isNull() const {
|
||||||
return _data == 0;
|
return data_ == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the reference is bound.
|
// Returns true if the reference is bound.
|
||||||
// https://arduinojson.org/v6/api/jsonarray/isnull/
|
// https://arduinojson.org/v6/api/jsonarray/isnull/
|
||||||
FORCE_INLINE operator bool() const {
|
FORCE_INLINE operator bool() const {
|
||||||
return _data != 0;
|
return data_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of bytes occupied by the array.
|
// Returns the number of bytes occupied by the array.
|
||||||
// https://arduinojson.org/v6/api/jsonarray/memoryusage/
|
// https://arduinojson.org/v6/api/jsonarray/memoryusage/
|
||||||
FORCE_INLINE size_t memoryUsage() const {
|
FORCE_INLINE size_t memoryUsage() const {
|
||||||
return _data ? _data->memoryUsage() : 0;
|
return data_ ? data_->memoryUsage() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the depth (nesting level) of the array.
|
// Returns the depth (nesting level) of the array.
|
||||||
// https://arduinojson.org/v6/api/jsonarray/nesting/
|
// https://arduinojson.org/v6/api/jsonarray/nesting/
|
||||||
FORCE_INLINE size_t nesting() const {
|
FORCE_INLINE size_t nesting() const {
|
||||||
return variantNesting(collectionToVariant(_data));
|
return variantNesting(collectionToVariant(data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of elements in the array.
|
// Returns the number of elements in the array.
|
||||||
// https://arduinojson.org/v6/api/jsonarray/size/
|
// https://arduinojson.org/v6/api/jsonarray/size/
|
||||||
FORCE_INLINE size_t size() const {
|
FORCE_INLINE size_t size() const {
|
||||||
return _data ? _data->size() : 0;
|
return data_ ? data_->size() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
detail::MemoryPool* getPool() const {
|
detail::MemoryPool* getPool() const {
|
||||||
return _pool;
|
return pool_;
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::VariantData* getData() const {
|
detail::VariantData* getData() const {
|
||||||
return collectionToVariant(_data);
|
return collectionToVariant(data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::VariantData* getOrCreateData() const {
|
detail::VariantData* getOrCreateData() const {
|
||||||
return collectionToVariant(_data);
|
return collectionToVariant(data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::CollectionData* _data;
|
detail::CollectionData* data_;
|
||||||
detail::MemoryPool* _pool;
|
detail::MemoryPool* pool_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
|
|||||||
// Returns an iterator to the first element of the array.
|
// Returns an iterator to the first element of the array.
|
||||||
// https://arduinojson.org/v6/api/jsonarrayconst/begin/
|
// https://arduinojson.org/v6/api/jsonarrayconst/begin/
|
||||||
FORCE_INLINE iterator begin() const {
|
FORCE_INLINE iterator begin() const {
|
||||||
if (!_data)
|
if (!data_)
|
||||||
return iterator();
|
return iterator();
|
||||||
return iterator(_data->head());
|
return iterator(data_->head());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an iterator to the element following the last element of the array.
|
// Returns an iterator to the element following the last element of the array.
|
||||||
@@ -36,18 +36,18 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Creates an unbound reference.
|
// Creates an unbound reference.
|
||||||
FORCE_INLINE JsonArrayConst() : _data(0) {}
|
FORCE_INLINE JsonArrayConst() : data_(0) {}
|
||||||
|
|
||||||
// INTERNAL USE ONLY
|
// INTERNAL USE ONLY
|
||||||
FORCE_INLINE JsonArrayConst(const detail::CollectionData* data)
|
FORCE_INLINE JsonArrayConst(const detail::CollectionData* data)
|
||||||
: _data(data) {}
|
: data_(data) {}
|
||||||
|
|
||||||
// Compares the content of two arrays.
|
// Compares the content of two arrays.
|
||||||
// Returns true if the two arrays are equal.
|
// Returns true if the two arrays are equal.
|
||||||
FORCE_INLINE bool operator==(JsonArrayConst rhs) const {
|
FORCE_INLINE bool operator==(JsonArrayConst rhs) const {
|
||||||
if (_data == rhs._data)
|
if (data_ == rhs.data_)
|
||||||
return true;
|
return true;
|
||||||
if (!_data || !rhs._data)
|
if (!data_ || !rhs.data_)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
iterator it1 = begin();
|
iterator it1 = begin();
|
||||||
@@ -70,49 +70,49 @@ class JsonArrayConst : public detail::VariantOperators<JsonArrayConst> {
|
|||||||
// Returns the element at the specified index.
|
// Returns the element at the specified index.
|
||||||
// https://arduinojson.org/v6/api/jsonarrayconst/subscript/
|
// https://arduinojson.org/v6/api/jsonarrayconst/subscript/
|
||||||
FORCE_INLINE JsonVariantConst operator[](size_t index) const {
|
FORCE_INLINE JsonVariantConst operator[](size_t index) const {
|
||||||
return JsonVariantConst(_data ? _data->getElement(index) : 0);
|
return JsonVariantConst(data_ ? data_->getElement(index) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
operator JsonVariantConst() const {
|
operator JsonVariantConst() const {
|
||||||
return JsonVariantConst(collectionToVariant(_data));
|
return JsonVariantConst(collectionToVariant(data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the reference is unbound.
|
// Returns true if the reference is unbound.
|
||||||
// https://arduinojson.org/v6/api/jsonarrayconst/isnull/
|
// https://arduinojson.org/v6/api/jsonarrayconst/isnull/
|
||||||
FORCE_INLINE bool isNull() const {
|
FORCE_INLINE bool isNull() const {
|
||||||
return _data == 0;
|
return data_ == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the reference is bound.
|
// Returns true if the reference is bound.
|
||||||
// https://arduinojson.org/v6/api/jsonarrayconst/isnull/
|
// https://arduinojson.org/v6/api/jsonarrayconst/isnull/
|
||||||
FORCE_INLINE operator bool() const {
|
FORCE_INLINE operator bool() const {
|
||||||
return _data != 0;
|
return data_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of bytes occupied by the array.
|
// Returns the number of bytes occupied by the array.
|
||||||
// https://arduinojson.org/v6/api/jsonarrayconst/memoryusage/
|
// https://arduinojson.org/v6/api/jsonarrayconst/memoryusage/
|
||||||
FORCE_INLINE size_t memoryUsage() const {
|
FORCE_INLINE size_t memoryUsage() const {
|
||||||
return _data ? _data->memoryUsage() : 0;
|
return data_ ? data_->memoryUsage() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the depth (nesting level) of the array.
|
// Returns the depth (nesting level) of the array.
|
||||||
// https://arduinojson.org/v6/api/jsonarrayconst/nesting/
|
// https://arduinojson.org/v6/api/jsonarrayconst/nesting/
|
||||||
FORCE_INLINE size_t nesting() const {
|
FORCE_INLINE size_t nesting() const {
|
||||||
return variantNesting(collectionToVariant(_data));
|
return variantNesting(collectionToVariant(data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of elements in the array.
|
// Returns the number of elements in the array.
|
||||||
// https://arduinojson.org/v6/api/jsonarrayconst/size/
|
// https://arduinojson.org/v6/api/jsonarrayconst/size/
|
||||||
FORCE_INLINE size_t size() const {
|
FORCE_INLINE size_t size() const {
|
||||||
return _data ? _data->size() : 0;
|
return data_ ? data_->size() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const detail::VariantData* getData() const {
|
const detail::VariantData* getData() const {
|
||||||
return collectionToVariant(_data);
|
return collectionToVariant(data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
const detail::CollectionData* _data;
|
const detail::CollectionData* data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|||||||
@@ -12,110 +12,110 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
|||||||
class VariantPtr {
|
class VariantPtr {
|
||||||
public:
|
public:
|
||||||
VariantPtr(detail::MemoryPool* pool, detail::VariantData* data)
|
VariantPtr(detail::MemoryPool* pool, detail::VariantData* data)
|
||||||
: _variant(pool, data) {}
|
: variant_(pool, data) {}
|
||||||
|
|
||||||
JsonVariant* operator->() {
|
JsonVariant* operator->() {
|
||||||
return &_variant;
|
return &variant_;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonVariant& operator*() {
|
JsonVariant& operator*() {
|
||||||
return _variant;
|
return variant_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JsonVariant _variant;
|
JsonVariant variant_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonArrayIterator {
|
class JsonArrayIterator {
|
||||||
friend class JsonArray;
|
friend class JsonArray;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JsonArrayIterator() : _slot(0) {}
|
JsonArrayIterator() : slot_(0) {}
|
||||||
explicit JsonArrayIterator(detail::MemoryPool* pool,
|
explicit JsonArrayIterator(detail::MemoryPool* pool,
|
||||||
detail::VariantSlot* slot)
|
detail::VariantSlot* slot)
|
||||||
: _pool(pool), _slot(slot) {}
|
: pool_(pool), slot_(slot) {}
|
||||||
|
|
||||||
JsonVariant operator*() const {
|
JsonVariant operator*() const {
|
||||||
return JsonVariant(_pool, _slot->data());
|
return JsonVariant(pool_, slot_->data());
|
||||||
}
|
}
|
||||||
VariantPtr operator->() {
|
VariantPtr operator->() {
|
||||||
return VariantPtr(_pool, _slot->data());
|
return VariantPtr(pool_, slot_->data());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const JsonArrayIterator& other) const {
|
bool operator==(const JsonArrayIterator& other) const {
|
||||||
return _slot == other._slot;
|
return slot_ == other.slot_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const JsonArrayIterator& other) const {
|
bool operator!=(const JsonArrayIterator& other) const {
|
||||||
return _slot != other._slot;
|
return slot_ != other.slot_;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonArrayIterator& operator++() {
|
JsonArrayIterator& operator++() {
|
||||||
_slot = _slot->next();
|
slot_ = slot_->next();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonArrayIterator& operator+=(size_t distance) {
|
JsonArrayIterator& operator+=(size_t distance) {
|
||||||
_slot = _slot->next(distance);
|
slot_ = slot_->next(distance);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
detail::MemoryPool* _pool;
|
detail::MemoryPool* pool_;
|
||||||
detail::VariantSlot* _slot;
|
detail::VariantSlot* slot_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class VariantConstPtr {
|
class VariantConstPtr {
|
||||||
public:
|
public:
|
||||||
VariantConstPtr(const detail::VariantData* data) : _variant(data) {}
|
VariantConstPtr(const detail::VariantData* data) : variant_(data) {}
|
||||||
|
|
||||||
JsonVariantConst* operator->() {
|
JsonVariantConst* operator->() {
|
||||||
return &_variant;
|
return &variant_;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonVariantConst& operator*() {
|
JsonVariantConst& operator*() {
|
||||||
return _variant;
|
return variant_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JsonVariantConst _variant;
|
JsonVariantConst variant_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonArrayConstIterator {
|
class JsonArrayConstIterator {
|
||||||
friend class JsonArray;
|
friend class JsonArray;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JsonArrayConstIterator() : _slot(0) {}
|
JsonArrayConstIterator() : slot_(0) {}
|
||||||
explicit JsonArrayConstIterator(const detail::VariantSlot* slot)
|
explicit JsonArrayConstIterator(const detail::VariantSlot* slot)
|
||||||
: _slot(slot) {}
|
: slot_(slot) {}
|
||||||
|
|
||||||
JsonVariantConst operator*() const {
|
JsonVariantConst operator*() const {
|
||||||
return JsonVariantConst(_slot->data());
|
return JsonVariantConst(slot_->data());
|
||||||
}
|
}
|
||||||
VariantConstPtr operator->() {
|
VariantConstPtr operator->() {
|
||||||
return VariantConstPtr(_slot->data());
|
return VariantConstPtr(slot_->data());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const JsonArrayConstIterator& other) const {
|
bool operator==(const JsonArrayConstIterator& other) const {
|
||||||
return _slot == other._slot;
|
return slot_ == other.slot_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const JsonArrayConstIterator& other) const {
|
bool operator!=(const JsonArrayConstIterator& other) const {
|
||||||
return _slot != other._slot;
|
return slot_ != other.slot_;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonArrayConstIterator& operator++() {
|
JsonArrayConstIterator& operator++() {
|
||||||
_slot = _slot->next();
|
slot_ = slot_->next();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonArrayConstIterator& operator+=(size_t distance) {
|
JsonArrayConstIterator& operator+=(size_t distance) {
|
||||||
_slot = _slot->next(distance);
|
slot_ = slot_->next(distance);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const detail::VariantSlot* _slot;
|
const detail::VariantSlot* slot_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ class VariantData;
|
|||||||
class VariantSlot;
|
class VariantSlot;
|
||||||
|
|
||||||
class CollectionData {
|
class CollectionData {
|
||||||
VariantSlot* _head;
|
VariantSlot* head_;
|
||||||
VariantSlot* _tail;
|
VariantSlot* tail_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Must be a POD!
|
// Must be a POD!
|
||||||
@@ -67,7 +67,7 @@ class CollectionData {
|
|||||||
bool copyFrom(const CollectionData& src, MemoryPool* pool);
|
bool copyFrom(const CollectionData& src, MemoryPool* pool);
|
||||||
|
|
||||||
VariantSlot* head() const {
|
VariantSlot* head() const {
|
||||||
return _head;
|
return head_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance);
|
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance);
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) {
|
|||||||
if (!slot)
|
if (!slot)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (_tail) {
|
if (tail_) {
|
||||||
ARDUINOJSON_ASSERT(pool->owns(_tail)); // Can't alter a linked array/object
|
ARDUINOJSON_ASSERT(pool->owns(tail_)); // Can't alter a linked array/object
|
||||||
_tail->setNextNotNull(slot);
|
tail_->setNextNotNull(slot);
|
||||||
_tail = slot;
|
tail_ = slot;
|
||||||
} else {
|
} else {
|
||||||
_head = slot;
|
head_ = slot;
|
||||||
_tail = slot;
|
tail_ = slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
slot->clear();
|
slot->clear();
|
||||||
@@ -45,8 +45,8 @@ inline VariantData* CollectionData::addMember(TAdaptedString key,
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void CollectionData::clear() {
|
inline void CollectionData::clear() {
|
||||||
_head = 0;
|
head_ = 0;
|
||||||
_tail = 0;
|
tail_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
@@ -57,7 +57,7 @@ inline bool CollectionData::containsKey(const TAdaptedString& key) const {
|
|||||||
inline bool CollectionData::copyFrom(const CollectionData& src,
|
inline bool CollectionData::copyFrom(const CollectionData& src,
|
||||||
MemoryPool* pool) {
|
MemoryPool* pool) {
|
||||||
clear();
|
clear();
|
||||||
for (VariantSlot* s = src._head; s; s = s->next()) {
|
for (VariantSlot* s = src.head_; s; s = s->next()) {
|
||||||
VariantData* var;
|
VariantData* var;
|
||||||
if (s->key() != 0) {
|
if (s->key() != 0) {
|
||||||
JsonString key(s->key(),
|
JsonString key(s->key(),
|
||||||
@@ -78,7 +78,7 @@ template <typename TAdaptedString>
|
|||||||
inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const {
|
inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const {
|
||||||
if (key.isNull())
|
if (key.isNull())
|
||||||
return 0;
|
return 0;
|
||||||
VariantSlot* slot = _head;
|
VariantSlot* slot = head_;
|
||||||
while (slot) {
|
while (slot) {
|
||||||
if (stringEquals(key, adaptString(slot->key())))
|
if (stringEquals(key, adaptString(slot->key())))
|
||||||
break;
|
break;
|
||||||
@@ -88,13 +88,13 @@ inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline VariantSlot* CollectionData::getSlot(size_t index) const {
|
inline VariantSlot* CollectionData::getSlot(size_t index) const {
|
||||||
if (!_head)
|
if (!head_)
|
||||||
return 0;
|
return 0;
|
||||||
return _head->next(index);
|
return head_->next(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const {
|
inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const {
|
||||||
VariantSlot* current = _head;
|
VariantSlot* current = head_;
|
||||||
while (current) {
|
while (current) {
|
||||||
VariantSlot* next = current->next();
|
VariantSlot* next = current->next();
|
||||||
if (next == target)
|
if (next == target)
|
||||||
@@ -132,7 +132,7 @@ inline VariantData* CollectionData::getElement(size_t index) const {
|
|||||||
|
|
||||||
inline VariantData* CollectionData::getOrAddElement(size_t index,
|
inline VariantData* CollectionData::getOrAddElement(size_t index,
|
||||||
MemoryPool* pool) {
|
MemoryPool* pool) {
|
||||||
VariantSlot* slot = _head;
|
VariantSlot* slot = head_;
|
||||||
while (slot && index > 0) {
|
while (slot && index > 0) {
|
||||||
slot = slot->next();
|
slot = slot->next();
|
||||||
index--;
|
index--;
|
||||||
@@ -154,9 +154,9 @@ inline void CollectionData::removeSlot(VariantSlot* slot) {
|
|||||||
if (prev)
|
if (prev)
|
||||||
prev->setNext(next);
|
prev->setNext(next);
|
||||||
else
|
else
|
||||||
_head = next;
|
head_ = next;
|
||||||
if (!next)
|
if (!next)
|
||||||
_tail = prev;
|
tail_ = prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void CollectionData::removeElement(size_t index) {
|
inline void CollectionData::removeElement(size_t index) {
|
||||||
@@ -165,7 +165,7 @@ inline void CollectionData::removeElement(size_t index) {
|
|||||||
|
|
||||||
inline size_t CollectionData::memoryUsage() const {
|
inline size_t CollectionData::memoryUsage() const {
|
||||||
size_t total = 0;
|
size_t total = 0;
|
||||||
for (VariantSlot* s = _head; s; s = s->next()) {
|
for (VariantSlot* s = head_; s; s = s->next()) {
|
||||||
total += sizeof(VariantSlot) + s->data()->memoryUsage();
|
total += sizeof(VariantSlot) + s->data()->memoryUsage();
|
||||||
if (s->ownsKey())
|
if (s->ownsKey())
|
||||||
total += strlen(s->key()) + 1;
|
total += strlen(s->key()) + 1;
|
||||||
@@ -174,7 +174,7 @@ inline size_t CollectionData::memoryUsage() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline size_t CollectionData::size() const {
|
inline size_t CollectionData::size() const {
|
||||||
return slotSize(_head);
|
return slotSize(head_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -188,9 +188,9 @@ inline void movePointer(T*& p, ptrdiff_t offset) {
|
|||||||
|
|
||||||
inline void CollectionData::movePointers(ptrdiff_t stringDistance,
|
inline void CollectionData::movePointers(ptrdiff_t stringDistance,
|
||||||
ptrdiff_t variantDistance) {
|
ptrdiff_t variantDistance) {
|
||||||
movePointer(_head, variantDistance);
|
movePointer(head_, variantDistance);
|
||||||
movePointer(_tail, variantDistance);
|
movePointer(tail_, variantDistance);
|
||||||
for (VariantSlot* slot = _head; slot; slot = slot->next())
|
for (VariantSlot* slot = head_; slot; slot = slot->next())
|
||||||
slot->movePointers(stringDistance, variantDistance);
|
slot->movePointers(stringDistance, variantDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -130,10 +130,14 @@
|
|||||||
# define ARDUINOJSON_ENABLE_ARDUINO_PRINT 0
|
# define ARDUINOJSON_ENABLE_ARDUINO_PRINT 0
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
// Disable support for PROGMEM
|
// Enable PROGMEM support on AVR only
|
||||||
# ifndef ARDUINOJSON_ENABLE_PROGMEM
|
# ifndef ARDUINOJSON_ENABLE_PROGMEM
|
||||||
|
# ifdef __AVR__
|
||||||
|
# define ARDUINOJSON_ENABLE_PROGMEM 1
|
||||||
|
# else
|
||||||
# define ARDUINOJSON_ENABLE_PROGMEM 0
|
# define ARDUINOJSON_ENABLE_PROGMEM 0
|
||||||
# endif
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
#endif // ARDUINO
|
#endif // ARDUINO
|
||||||
|
|
||||||
|
|||||||
@@ -26,49 +26,49 @@ class DeserializationError {
|
|||||||
};
|
};
|
||||||
|
|
||||||
DeserializationError() {}
|
DeserializationError() {}
|
||||||
DeserializationError(Code c) : _code(c) {}
|
DeserializationError(Code c) : code_(c) {}
|
||||||
|
|
||||||
// Compare with DeserializationError
|
// Compare with DeserializationError
|
||||||
friend bool operator==(const DeserializationError& lhs,
|
friend bool operator==(const DeserializationError& lhs,
|
||||||
const DeserializationError& rhs) {
|
const DeserializationError& rhs) {
|
||||||
return lhs._code == rhs._code;
|
return lhs.code_ == rhs.code_;
|
||||||
}
|
}
|
||||||
friend bool operator!=(const DeserializationError& lhs,
|
friend bool operator!=(const DeserializationError& lhs,
|
||||||
const DeserializationError& rhs) {
|
const DeserializationError& rhs) {
|
||||||
return lhs._code != rhs._code;
|
return lhs.code_ != rhs.code_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare with Code
|
// Compare with Code
|
||||||
friend bool operator==(const DeserializationError& lhs, Code rhs) {
|
friend bool operator==(const DeserializationError& lhs, Code rhs) {
|
||||||
return lhs._code == rhs;
|
return lhs.code_ == rhs;
|
||||||
}
|
}
|
||||||
friend bool operator==(Code lhs, const DeserializationError& rhs) {
|
friend bool operator==(Code lhs, const DeserializationError& rhs) {
|
||||||
return lhs == rhs._code;
|
return lhs == rhs.code_;
|
||||||
}
|
}
|
||||||
friend bool operator!=(const DeserializationError& lhs, Code rhs) {
|
friend bool operator!=(const DeserializationError& lhs, Code rhs) {
|
||||||
return lhs._code != rhs;
|
return lhs.code_ != rhs;
|
||||||
}
|
}
|
||||||
friend bool operator!=(Code lhs, const DeserializationError& rhs) {
|
friend bool operator!=(Code lhs, const DeserializationError& rhs) {
|
||||||
return lhs != rhs._code;
|
return lhs != rhs.code_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if there is an error
|
// Returns true if there is an error
|
||||||
explicit operator bool() const {
|
explicit operator bool() const {
|
||||||
return _code != Ok;
|
return code_ != Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns internal enum, useful for switch statement
|
// Returns internal enum, useful for switch statement
|
||||||
Code code() const {
|
Code code() const {
|
||||||
return _code;
|
return code_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* c_str() const {
|
const char* c_str() const {
|
||||||
static const char* messages[] = {
|
static const char* messages[] = {
|
||||||
"Ok", "EmptyInput", "IncompleteInput",
|
"Ok", "EmptyInput", "IncompleteInput",
|
||||||
"InvalidInput", "NoMemory", "TooDeep"};
|
"InvalidInput", "NoMemory", "TooDeep"};
|
||||||
ARDUINOJSON_ASSERT(static_cast<size_t>(_code) <
|
ARDUINOJSON_ASSERT(static_cast<size_t>(code_) <
|
||||||
sizeof(messages) / sizeof(messages[0]));
|
sizeof(messages) / sizeof(messages[0]));
|
||||||
return messages[_code];
|
return messages[code_];
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_PROGMEM
|
#if ARDUINOJSON_ENABLE_PROGMEM
|
||||||
@@ -82,12 +82,12 @@ class DeserializationError {
|
|||||||
ARDUINOJSON_DEFINE_PROGMEM_ARRAY(const char*, messages,
|
ARDUINOJSON_DEFINE_PROGMEM_ARRAY(const char*, messages,
|
||||||
{s0, s1, s2, s3, s4, s5});
|
{s0, s1, s2, s3, s4, s5});
|
||||||
return reinterpret_cast<const __FlashStringHelper*>(
|
return reinterpret_cast<const __FlashStringHelper*>(
|
||||||
detail::pgm_read(messages + _code));
|
detail::pgm_read(messages + code_));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Code _code;
|
Code code_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||||
|
|||||||
@@ -11,34 +11,34 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
|||||||
namespace DeserializationOption {
|
namespace DeserializationOption {
|
||||||
class Filter {
|
class Filter {
|
||||||
public:
|
public:
|
||||||
explicit Filter(JsonVariantConst v) : _variant(v) {}
|
explicit Filter(JsonVariantConst v) : variant_(v) {}
|
||||||
|
|
||||||
bool allow() const {
|
bool allow() const {
|
||||||
return _variant;
|
return variant_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool allowArray() const {
|
bool allowArray() const {
|
||||||
return _variant == true || _variant.is<JsonArrayConst>();
|
return variant_ == true || variant_.is<JsonArrayConst>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool allowObject() const {
|
bool allowObject() const {
|
||||||
return _variant == true || _variant.is<JsonObjectConst>();
|
return variant_ == true || variant_.is<JsonObjectConst>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool allowValue() const {
|
bool allowValue() const {
|
||||||
return _variant == true;
|
return variant_ == true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TKey>
|
template <typename TKey>
|
||||||
Filter operator[](const TKey& key) const {
|
Filter operator[](const TKey& key) const {
|
||||||
if (_variant == true) // "true" means "allow recursively"
|
if (variant_ == true) // "true" means "allow recursively"
|
||||||
return *this;
|
return *this;
|
||||||
JsonVariantConst member = _variant[key];
|
JsonVariantConst member = variant_[key];
|
||||||
return Filter(member.isNull() ? _variant["*"] : member);
|
return Filter(member.isNull() ? variant_["*"] : member);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JsonVariantConst _variant;
|
JsonVariantConst variant_;
|
||||||
};
|
};
|
||||||
} // namespace DeserializationOption
|
} // namespace DeserializationOption
|
||||||
|
|
||||||
|
|||||||
@@ -12,20 +12,20 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
|||||||
namespace DeserializationOption {
|
namespace DeserializationOption {
|
||||||
class NestingLimit {
|
class NestingLimit {
|
||||||
public:
|
public:
|
||||||
NestingLimit() : _value(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
|
NestingLimit() : value_(ARDUINOJSON_DEFAULT_NESTING_LIMIT) {}
|
||||||
explicit NestingLimit(uint8_t n) : _value(n) {}
|
explicit NestingLimit(uint8_t n) : value_(n) {}
|
||||||
|
|
||||||
NestingLimit decrement() const {
|
NestingLimit decrement() const {
|
||||||
ARDUINOJSON_ASSERT(_value > 0);
|
ARDUINOJSON_ASSERT(value_ > 0);
|
||||||
return NestingLimit(static_cast<uint8_t>(_value - 1));
|
return NestingLimit(static_cast<uint8_t>(value_ - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool reached() const {
|
bool reached() const {
|
||||||
return _value == 0;
|
return value_ == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t _value;
|
uint8_t value_;
|
||||||
};
|
};
|
||||||
} // namespace DeserializationOption
|
} // namespace DeserializationOption
|
||||||
|
|
||||||
|
|||||||
@@ -15,18 +15,18 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
|||||||
template <typename TSource, typename Enable = void>
|
template <typename TSource, typename Enable = void>
|
||||||
struct Reader {
|
struct Reader {
|
||||||
public:
|
public:
|
||||||
Reader(TSource& source) : _source(&source) {}
|
Reader(TSource& source) : source_(&source) {}
|
||||||
|
|
||||||
int read() {
|
int read() {
|
||||||
return _source->read(); // Error here? You passed an unsupported input type
|
return source_->read(); // Error here? You passed an unsupported input type
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t readBytes(char* buffer, size_t length) {
|
size_t readBytes(char* buffer, size_t length) {
|
||||||
return _source->readBytes(buffer, length);
|
return source_->readBytes(buffer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TSource* _source;
|
TSource* source_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TSource, typename Enable = void>
|
template <typename TSource, typename Enable = void>
|
||||||
|
|||||||
@@ -12,20 +12,20 @@ template <typename TSource>
|
|||||||
struct Reader<TSource,
|
struct Reader<TSource,
|
||||||
typename enable_if<is_base_of<Stream, TSource>::value>::type> {
|
typename enable_if<is_base_of<Stream, TSource>::value>::type> {
|
||||||
public:
|
public:
|
||||||
explicit Reader(Stream& stream) : _stream(&stream) {}
|
explicit Reader(Stream& stream) : stream_(&stream) {}
|
||||||
|
|
||||||
int read() {
|
int read() {
|
||||||
// don't use _stream.read() as it ignores the timeout
|
// don't use stream_.read() as it ignores the timeout
|
||||||
char c;
|
char c;
|
||||||
return _stream->readBytes(&c, 1) ? static_cast<unsigned char>(c) : -1;
|
return stream_->readBytes(&c, 1) ? static_cast<unsigned char>(c) : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t readBytes(char* buffer, size_t length) {
|
size_t readBytes(char* buffer, size_t length) {
|
||||||
return _stream->readBytes(buffer, length);
|
return stream_->readBytes(buffer, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Stream* _stream;
|
Stream* stream_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -4,51 +4,51 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <ArduinoJson/Polyfills/pgmspace.hpp>
|
||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct Reader<const __FlashStringHelper*, void> {
|
struct Reader<const __FlashStringHelper*, void> {
|
||||||
const char* _ptr;
|
const char* ptr_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Reader(const __FlashStringHelper* ptr)
|
explicit Reader(const __FlashStringHelper* ptr)
|
||||||
: _ptr(reinterpret_cast<const char*>(ptr)) {}
|
: ptr_(reinterpret_cast<const char*>(ptr)) {}
|
||||||
|
|
||||||
int read() {
|
int read() {
|
||||||
return pgm_read_byte(_ptr++);
|
return pgm_read_byte(ptr_++);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t readBytes(char* buffer, size_t length) {
|
size_t readBytes(char* buffer, size_t length) {
|
||||||
memcpy_P(buffer, _ptr, length);
|
memcpy_P(buffer, ptr_, length);
|
||||||
_ptr += length;
|
ptr_ += length;
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct BoundedReader<const __FlashStringHelper*, void> {
|
struct BoundedReader<const __FlashStringHelper*, void> {
|
||||||
const char* _ptr;
|
const char* ptr_;
|
||||||
const char* _end;
|
const char* end_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit BoundedReader(const __FlashStringHelper* ptr, size_t size)
|
explicit BoundedReader(const __FlashStringHelper* ptr, size_t size)
|
||||||
: _ptr(reinterpret_cast<const char*>(ptr)), _end(_ptr + size) {}
|
: ptr_(reinterpret_cast<const char*>(ptr)), end_(ptr_ + size) {}
|
||||||
|
|
||||||
int read() {
|
int read() {
|
||||||
if (_ptr < _end)
|
if (ptr_ < end_)
|
||||||
return pgm_read_byte(_ptr++);
|
return pgm_read_byte(ptr_++);
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t readBytes(char* buffer, size_t length) {
|
size_t readBytes(char* buffer, size_t length) {
|
||||||
size_t available = static_cast<size_t>(_end - _ptr);
|
size_t available = static_cast<size_t>(end_ - ptr_);
|
||||||
if (available < length)
|
if (available < length)
|
||||||
length = available;
|
length = available;
|
||||||
memcpy_P(buffer, _ptr, length);
|
memcpy_P(buffer, ptr_, length);
|
||||||
_ptr += length;
|
ptr_ += length;
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,23 +8,23 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
|||||||
|
|
||||||
template <typename TIterator>
|
template <typename TIterator>
|
||||||
class IteratorReader {
|
class IteratorReader {
|
||||||
TIterator _ptr, _end;
|
TIterator ptr_, end_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit IteratorReader(TIterator begin, TIterator end)
|
explicit IteratorReader(TIterator begin, TIterator end)
|
||||||
: _ptr(begin), _end(end) {}
|
: ptr_(begin), end_(end) {}
|
||||||
|
|
||||||
int read() {
|
int read() {
|
||||||
if (_ptr < _end)
|
if (ptr_ < end_)
|
||||||
return static_cast<unsigned char>(*_ptr++);
|
return static_cast<unsigned char>(*ptr_++);
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t readBytes(char* buffer, size_t length) {
|
size_t readBytes(char* buffer, size_t length) {
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
while (i < length && _ptr < _end)
|
while (i < length && ptr_ < end_)
|
||||||
buffer[i++] = *_ptr++;
|
buffer[i++] = *ptr_++;
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,19 +21,19 @@ struct IsCharOrVoid<const T> : IsCharOrVoid<T> {};
|
|||||||
template <typename TSource>
|
template <typename TSource>
|
||||||
struct Reader<TSource*,
|
struct Reader<TSource*,
|
||||||
typename enable_if<IsCharOrVoid<TSource>::value>::type> {
|
typename enable_if<IsCharOrVoid<TSource>::value>::type> {
|
||||||
const char* _ptr;
|
const char* ptr_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Reader(const void* ptr)
|
explicit Reader(const void* ptr)
|
||||||
: _ptr(ptr ? reinterpret_cast<const char*>(ptr) : "") {}
|
: ptr_(ptr ? reinterpret_cast<const char*>(ptr) : "") {}
|
||||||
|
|
||||||
int read() {
|
int read() {
|
||||||
return static_cast<unsigned char>(*_ptr++);
|
return static_cast<unsigned char>(*ptr_++);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t readBytes(char* buffer, size_t length) {
|
size_t readBytes(char* buffer, size_t length) {
|
||||||
for (size_t i = 0; i < length; i++)
|
for (size_t i = 0; i < length; i++)
|
||||||
buffer[i] = *_ptr++;
|
buffer[i] = *ptr_++;
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,19 +12,19 @@ template <typename TSource>
|
|||||||
struct Reader<TSource, typename enable_if<
|
struct Reader<TSource, typename enable_if<
|
||||||
is_base_of<std::istream, TSource>::value>::type> {
|
is_base_of<std::istream, TSource>::value>::type> {
|
||||||
public:
|
public:
|
||||||
explicit Reader(std::istream& stream) : _stream(&stream) {}
|
explicit Reader(std::istream& stream) : stream_(&stream) {}
|
||||||
|
|
||||||
int read() {
|
int read() {
|
||||||
return _stream->get();
|
return stream_->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t readBytes(char* buffer, size_t length) {
|
size_t readBytes(char* buffer, size_t length) {
|
||||||
_stream->read(buffer, static_cast<std::streamsize>(length));
|
stream_->read(buffer, static_cast<std::streamsize>(length));
|
||||||
return static_cast<size_t>(_stream->gcount());
|
return static_cast<size_t>(stream_->gcount());
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::istream* _stream;
|
std::istream* stream_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -12,6 +12,17 @@
|
|||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
|
// A meta-function that returns the first type of the parameter pack
|
||||||
|
// or void if empty
|
||||||
|
template <typename...>
|
||||||
|
struct first_or_void {
|
||||||
|
using type = void;
|
||||||
|
};
|
||||||
|
template <typename T, typename... Rest>
|
||||||
|
struct first_or_void<T, Rest...> {
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
|
||||||
template <template <typename, typename> class TDeserializer, typename TReader,
|
template <template <typename, typename> class TDeserializer, typename TReader,
|
||||||
typename TWriter>
|
typename TWriter>
|
||||||
TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool* pool,
|
TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool* pool,
|
||||||
@@ -22,7 +33,9 @@ TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool* pool,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <template <typename, typename> class TDeserializer, typename TStream,
|
template <template <typename, typename> class TDeserializer, typename TStream,
|
||||||
typename... Args>
|
typename... Args,
|
||||||
|
typename = typename enable_if< // issue #1897
|
||||||
|
!is_integral<typename first_or_void<Args...>::type>::value>::type>
|
||||||
DeserializationError deserialize(JsonDocument& doc, TStream&& input,
|
DeserializationError deserialize(JsonDocument& doc, TStream&& input,
|
||||||
Args... args) {
|
Args... args) {
|
||||||
auto reader = makeReader(detail::forward<TStream>(input));
|
auto reader = makeReader(detail::forward<TStream>(input));
|
||||||
|
|||||||
@@ -14,27 +14,27 @@ template <typename TAllocator>
|
|||||||
class AllocatorOwner {
|
class AllocatorOwner {
|
||||||
public:
|
public:
|
||||||
AllocatorOwner() {}
|
AllocatorOwner() {}
|
||||||
AllocatorOwner(TAllocator a) : _allocator(a) {}
|
AllocatorOwner(TAllocator a) : allocator_(a) {}
|
||||||
|
|
||||||
void* allocate(size_t size) {
|
void* allocate(size_t size) {
|
||||||
return _allocator.allocate(size);
|
return allocator_.allocate(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void deallocate(void* ptr) {
|
void deallocate(void* ptr) {
|
||||||
if (ptr)
|
if (ptr)
|
||||||
_allocator.deallocate(ptr);
|
allocator_.deallocate(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* reallocate(void* ptr, size_t new_size) {
|
void* reallocate(void* ptr, size_t new_size) {
|
||||||
return _allocator.reallocate(ptr, new_size);
|
return allocator_.reallocate(ptr, new_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
TAllocator& allocator() {
|
TAllocator& allocator() {
|
||||||
return _allocator;
|
return allocator_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TAllocator _allocator;
|
TAllocator allocator_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A JsonDocument that uses the provided allocator to allocate its memory pool.
|
// A JsonDocument that uses the provided allocator to allocate its memory pool.
|
||||||
@@ -106,18 +106,18 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
|
|||||||
// Reduces the capacity of the memory pool to match the current usage.
|
// Reduces the capacity of the memory pool to match the current usage.
|
||||||
// https://arduinojson.org/v6/api/basicjsondocument/shrinktofit/
|
// https://arduinojson.org/v6/api/basicjsondocument/shrinktofit/
|
||||||
void shrinkToFit() {
|
void shrinkToFit() {
|
||||||
ptrdiff_t bytes_reclaimed = _pool.squash();
|
ptrdiff_t bytes_reclaimed = pool_.squash();
|
||||||
if (bytes_reclaimed == 0)
|
if (bytes_reclaimed == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
void* old_ptr = _pool.buffer();
|
void* old_ptr = pool_.buffer();
|
||||||
void* new_ptr = this->reallocate(old_ptr, _pool.capacity());
|
void* new_ptr = this->reallocate(old_ptr, pool_.capacity());
|
||||||
|
|
||||||
ptrdiff_t ptr_offset =
|
ptrdiff_t ptr_offset =
|
||||||
static_cast<char*>(new_ptr) - static_cast<char*>(old_ptr);
|
static_cast<char*>(new_ptr) - static_cast<char*>(old_ptr);
|
||||||
|
|
||||||
_pool.movePointers(ptr_offset);
|
pool_.movePointers(ptr_offset);
|
||||||
_data.movePointers(ptr_offset, ptr_offset - bytes_reclaimed);
|
data_.movePointers(ptr_offset, ptr_offset - bytes_reclaimed);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reclaims the memory leaked when removing and replacing values.
|
// Reclaims the memory leaked when removing and replacing values.
|
||||||
@@ -127,7 +127,6 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
|
|||||||
BasicJsonDocument tmp(*this);
|
BasicJsonDocument tmp(*this);
|
||||||
if (!tmp.capacity())
|
if (!tmp.capacity())
|
||||||
return false;
|
return false;
|
||||||
tmp.set(*this);
|
|
||||||
moveAssignFrom(tmp);
|
moveAssignFrom(tmp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -142,7 +141,7 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
|
|||||||
|
|
||||||
void reallocPool(size_t requiredSize) {
|
void reallocPool(size_t requiredSize) {
|
||||||
size_t capa = detail::addPadding(requiredSize);
|
size_t capa = detail::addPadding(requiredSize);
|
||||||
if (capa == _pool.capacity())
|
if (capa == pool_.capacity())
|
||||||
return;
|
return;
|
||||||
freePool();
|
freePool();
|
||||||
replacePool(allocPool(detail::addPadding(requiredSize)));
|
replacePool(allocPool(detail::addPadding(requiredSize)));
|
||||||
@@ -159,10 +158,10 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
|
|||||||
|
|
||||||
void moveAssignFrom(BasicJsonDocument& src) {
|
void moveAssignFrom(BasicJsonDocument& src) {
|
||||||
freePool();
|
freePool();
|
||||||
_data = src._data;
|
data_ = src.data_;
|
||||||
_pool = src._pool;
|
pool_ = src.pool_;
|
||||||
src._data.setNull();
|
src.data_.setNull();
|
||||||
src._pool = {0, 0};
|
src.pool_ = {0, 0};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
// Empties the document and resets the memory pool
|
// Empties the document and resets the memory pool
|
||||||
// https://arduinojson.org/v6/api/jsondocument/clear/
|
// https://arduinojson.org/v6/api/jsondocument/clear/
|
||||||
void clear() {
|
void clear() {
|
||||||
_pool.clear();
|
pool_.clear();
|
||||||
_data.init();
|
data_.setNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the root is of the specified type.
|
// Returns true if the root is of the specified type.
|
||||||
@@ -67,31 +67,31 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
// Returns the number of used bytes in the memory pool.
|
// Returns the number of used bytes in the memory pool.
|
||||||
// https://arduinojson.org/v6/api/jsondocument/memoryusage/
|
// https://arduinojson.org/v6/api/jsondocument/memoryusage/
|
||||||
size_t memoryUsage() const {
|
size_t memoryUsage() const {
|
||||||
return _pool.size();
|
return pool_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns trues if the memory pool was too small.
|
// Returns trues if the memory pool was too small.
|
||||||
// https://arduinojson.org/v6/api/jsondocument/overflowed/
|
// https://arduinojson.org/v6/api/jsondocument/overflowed/
|
||||||
bool overflowed() const {
|
bool overflowed() const {
|
||||||
return _pool.overflowed();
|
return pool_.overflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the depth (nesting level) of the array.
|
// Returns the depth (nesting level) of the array.
|
||||||
// https://arduinojson.org/v6/api/jsondocument/nesting/
|
// https://arduinojson.org/v6/api/jsondocument/nesting/
|
||||||
size_t nesting() const {
|
size_t nesting() const {
|
||||||
return variantNesting(&_data);
|
return variantNesting(&data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the capacity of the memory pool.
|
// Returns the capacity of the memory pool.
|
||||||
// https://arduinojson.org/v6/api/jsondocument/capacity/
|
// https://arduinojson.org/v6/api/jsondocument/capacity/
|
||||||
size_t capacity() const {
|
size_t capacity() const {
|
||||||
return _pool.capacity();
|
return pool_.capacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of elements in the root array or object.
|
// Returns the number of elements in the root array or object.
|
||||||
// https://arduinojson.org/v6/api/jsondocument/size/
|
// https://arduinojson.org/v6/api/jsondocument/size/
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return _data.size();
|
return data_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copies the specified document.
|
// Copies the specified document.
|
||||||
@@ -161,14 +161,14 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
// https://arduinojson.org/v6/api/jsondocument/containskey/
|
// https://arduinojson.org/v6/api/jsondocument/containskey/
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
bool containsKey(TChar* key) const {
|
bool containsKey(TChar* key) const {
|
||||||
return _data.getMember(detail::adaptString(key)) != 0;
|
return data_.getMember(detail::adaptString(key)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the root object contains the specified key.
|
// Returns true if the root object contains the specified key.
|
||||||
// https://arduinojson.org/v6/api/jsondocument/containskey/
|
// https://arduinojson.org/v6/api/jsondocument/containskey/
|
||||||
template <typename TString>
|
template <typename TString>
|
||||||
bool containsKey(const TString& key) const {
|
bool containsKey(const TString& key) const {
|
||||||
return _data.getMember(detail::adaptString(key)) != 0;
|
return data_.getMember(detail::adaptString(key)) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets or sets a root object's member.
|
// Gets or sets a root object's member.
|
||||||
@@ -197,7 +197,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
FORCE_INLINE typename detail::enable_if<detail::IsString<TString>::value,
|
FORCE_INLINE typename detail::enable_if<detail::IsString<TString>::value,
|
||||||
JsonVariantConst>::type
|
JsonVariantConst>::type
|
||||||
operator[](const TString& key) const {
|
operator[](const TString& key) const {
|
||||||
return JsonVariantConst(_data.getMember(detail::adaptString(key)));
|
return JsonVariantConst(data_.getMember(detail::adaptString(key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets a root object's member.
|
// Gets a root object's member.
|
||||||
@@ -206,7 +206,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
FORCE_INLINE typename detail::enable_if<detail::IsString<TChar*>::value,
|
FORCE_INLINE typename detail::enable_if<detail::IsString<TChar*>::value,
|
||||||
JsonVariantConst>::type
|
JsonVariantConst>::type
|
||||||
operator[](TChar* key) const {
|
operator[](TChar* key) const {
|
||||||
return JsonVariantConst(_data.getMember(detail::adaptString(key)));
|
return JsonVariantConst(data_.getMember(detail::adaptString(key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets or sets a root array's element.
|
// Gets or sets a root array's element.
|
||||||
@@ -218,14 +218,14 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
// Gets a root array's member.
|
// Gets a root array's member.
|
||||||
// https://arduinojson.org/v6/api/jsondocument/subscript/
|
// https://arduinojson.org/v6/api/jsondocument/subscript/
|
||||||
FORCE_INLINE JsonVariantConst operator[](size_t index) const {
|
FORCE_INLINE JsonVariantConst operator[](size_t index) const {
|
||||||
return JsonVariantConst(_data.getElement(index));
|
return JsonVariantConst(data_.getElement(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends a new (null) element to the root array.
|
// Appends a new (null) element to the root array.
|
||||||
// Returns a reference to the new element.
|
// Returns a reference to the new element.
|
||||||
// https://arduinojson.org/v6/api/jsondocument/add/
|
// https://arduinojson.org/v6/api/jsondocument/add/
|
||||||
FORCE_INLINE JsonVariant add() {
|
FORCE_INLINE JsonVariant add() {
|
||||||
return JsonVariant(&_pool, _data.addElement(&_pool));
|
return JsonVariant(&pool_, data_.addElement(&pool_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Appends a value to the root array.
|
// Appends a value to the root array.
|
||||||
@@ -246,7 +246,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
// ⚠️ Doesn't release the memory associated with the removed element.
|
// ⚠️ Doesn't release the memory associated with the removed element.
|
||||||
// https://arduinojson.org/v6/api/jsondocument/remove/
|
// https://arduinojson.org/v6/api/jsondocument/remove/
|
||||||
FORCE_INLINE void remove(size_t index) {
|
FORCE_INLINE void remove(size_t index) {
|
||||||
_data.remove(index);
|
data_.remove(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes a member of the root object.
|
// Removes a member of the root object.
|
||||||
@@ -255,7 +255,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
FORCE_INLINE typename detail::enable_if<detail::IsString<TChar*>::value>::type
|
FORCE_INLINE typename detail::enable_if<detail::IsString<TChar*>::value>::type
|
||||||
remove(TChar* key) {
|
remove(TChar* key) {
|
||||||
_data.remove(detail::adaptString(key));
|
data_.remove(detail::adaptString(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes a member of the root object.
|
// Removes a member of the root object.
|
||||||
@@ -265,7 +265,7 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
FORCE_INLINE
|
FORCE_INLINE
|
||||||
typename detail::enable_if<detail::IsString<TString>::value>::type
|
typename detail::enable_if<detail::IsString<TString>::value>::type
|
||||||
remove(const TString& key) {
|
remove(const TString& key) {
|
||||||
_data.remove(detail::adaptString(key));
|
data_.remove(detail::adaptString(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE operator JsonVariant() {
|
FORCE_INLINE operator JsonVariant() {
|
||||||
@@ -277,50 +277,44 @@ class JsonDocument : public detail::VariantOperators<const JsonDocument&> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
JsonDocument() : _pool(0, 0) {
|
JsonDocument() : pool_(0, 0) {}
|
||||||
_data.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonDocument(detail::MemoryPool pool) : _pool(pool) {
|
JsonDocument(detail::MemoryPool pool) : pool_(pool) {}
|
||||||
_data.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonDocument(char* buf, size_t capa) : _pool(buf, capa) {
|
JsonDocument(char* buf, size_t capa) : pool_(buf, capa) {}
|
||||||
_data.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
~JsonDocument() {}
|
~JsonDocument() {}
|
||||||
|
|
||||||
void replacePool(detail::MemoryPool pool) {
|
void replacePool(detail::MemoryPool pool) {
|
||||||
_pool = pool;
|
pool_ = pool;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonVariant getVariant() {
|
JsonVariant getVariant() {
|
||||||
return JsonVariant(&_pool, &_data);
|
return JsonVariant(&pool_, &data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonVariantConst getVariant() const {
|
JsonVariantConst getVariant() const {
|
||||||
return JsonVariantConst(&_data);
|
return JsonVariantConst(&data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::MemoryPool _pool;
|
detail::MemoryPool pool_;
|
||||||
detail::VariantData _data;
|
detail::VariantData data_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
detail::MemoryPool* getPool() {
|
detail::MemoryPool* getPool() {
|
||||||
return &_pool;
|
return &pool_;
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::VariantData* getData() {
|
detail::VariantData* getData() {
|
||||||
return &_data;
|
return &data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const detail::VariantData* getData() const {
|
const detail::VariantData* getData() const {
|
||||||
return &_data;
|
return &data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::VariantData* getOrCreateData() {
|
detail::VariantData* getOrCreateData() {
|
||||||
return &_data;
|
return &data_;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,14 +11,14 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
|||||||
// A JsonDocument with a memory pool on the stack.
|
// A JsonDocument with a memory pool on the stack.
|
||||||
template <size_t desiredCapacity>
|
template <size_t desiredCapacity>
|
||||||
class StaticJsonDocument : public JsonDocument {
|
class StaticJsonDocument : public JsonDocument {
|
||||||
static const size_t _capacity =
|
static const size_t capacity_ =
|
||||||
detail::AddPadding<detail::Max<1, desiredCapacity>::value>::value;
|
detail::AddPadding<detail::Max<1, desiredCapacity>::value>::value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StaticJsonDocument() : JsonDocument(_buffer, _capacity) {}
|
StaticJsonDocument() : JsonDocument(buffer_, capacity_) {}
|
||||||
|
|
||||||
StaticJsonDocument(const StaticJsonDocument& src)
|
StaticJsonDocument(const StaticJsonDocument& src)
|
||||||
: JsonDocument(_buffer, _capacity) {
|
: JsonDocument(buffer_, capacity_) {
|
||||||
set(src);
|
set(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,12 +27,12 @@ class StaticJsonDocument : public JsonDocument {
|
|||||||
const T& src,
|
const T& src,
|
||||||
typename detail::enable_if<
|
typename detail::enable_if<
|
||||||
detail::is_convertible<T, JsonVariantConst>::value>::type* = 0)
|
detail::is_convertible<T, JsonVariantConst>::value>::type* = 0)
|
||||||
: JsonDocument(_buffer, _capacity) {
|
: JsonDocument(buffer_, capacity_) {
|
||||||
set(src);
|
set(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
// disambiguate
|
// disambiguate
|
||||||
StaticJsonDocument(JsonVariant src) : JsonDocument(_buffer, _capacity) {
|
StaticJsonDocument(JsonVariant src) : JsonDocument(buffer_, capacity_) {
|
||||||
set(src);
|
set(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ class StaticJsonDocument : public JsonDocument {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char _buffer[_capacity];
|
char buffer_[capacity_];
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
||||||
|
|||||||
@@ -23,10 +23,10 @@ class JsonDeserializer {
|
|||||||
public:
|
public:
|
||||||
JsonDeserializer(MemoryPool* pool, TReader reader,
|
JsonDeserializer(MemoryPool* pool, TReader reader,
|
||||||
TStringStorage stringStorage)
|
TStringStorage stringStorage)
|
||||||
: _stringStorage(stringStorage),
|
: stringStorage_(stringStorage),
|
||||||
_foundSomething(false),
|
foundSomething_(false),
|
||||||
_latch(reader),
|
latch_(reader),
|
||||||
_pool(pool) {}
|
pool_(pool) {}
|
||||||
|
|
||||||
template <typename TFilter>
|
template <typename TFilter>
|
||||||
DeserializationError parse(VariantData& variant, TFilter filter,
|
DeserializationError parse(VariantData& variant, TFilter filter,
|
||||||
@@ -35,7 +35,7 @@ class JsonDeserializer {
|
|||||||
|
|
||||||
err = parseVariant(variant, filter, nestingLimit);
|
err = parseVariant(variant, filter, nestingLimit);
|
||||||
|
|
||||||
if (!err && _latch.last() != 0 && !variant.isEnclosed()) {
|
if (!err && latch_.last() != 0 && !variant.isEnclosed()) {
|
||||||
// We don't detect trailing characters earlier, so we need to check now
|
// We don't detect trailing characters earlier, so we need to check now
|
||||||
return DeserializationError::InvalidInput;
|
return DeserializationError::InvalidInput;
|
||||||
}
|
}
|
||||||
@@ -45,11 +45,11 @@ class JsonDeserializer {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
char current() {
|
char current() {
|
||||||
return _latch.current();
|
return latch_.current();
|
||||||
}
|
}
|
||||||
|
|
||||||
void move() {
|
void move() {
|
||||||
_latch.clear();
|
latch_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool eat(char charToSkip) {
|
bool eat(char charToSkip) {
|
||||||
@@ -173,7 +173,7 @@ class JsonDeserializer {
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
if (memberFilter.allow()) {
|
if (memberFilter.allow()) {
|
||||||
// Allocate slot in array
|
// Allocate slot in array
|
||||||
VariantData* value = array.addElement(_pool);
|
VariantData* value = array.addElement(pool_);
|
||||||
if (!value)
|
if (!value)
|
||||||
return DeserializationError::NoMemory;
|
return DeserializationError::NoMemory;
|
||||||
|
|
||||||
@@ -269,7 +269,7 @@ class JsonDeserializer {
|
|||||||
if (!eat(':'))
|
if (!eat(':'))
|
||||||
return DeserializationError::InvalidInput;
|
return DeserializationError::InvalidInput;
|
||||||
|
|
||||||
JsonString key = _stringStorage.str();
|
JsonString key = stringStorage_.str();
|
||||||
|
|
||||||
TFilter memberFilter = filter[key.c_str()];
|
TFilter memberFilter = filter[key.c_str()];
|
||||||
|
|
||||||
@@ -278,10 +278,10 @@ class JsonDeserializer {
|
|||||||
if (!variant) {
|
if (!variant) {
|
||||||
// Save key in memory pool.
|
// Save key in memory pool.
|
||||||
// This MUST be done before adding the slot.
|
// This MUST be done before adding the slot.
|
||||||
key = _stringStorage.save();
|
key = stringStorage_.save();
|
||||||
|
|
||||||
// Allocate slot in object
|
// Allocate slot in object
|
||||||
VariantSlot* slot = object.addSlot(_pool);
|
VariantSlot* slot = object.addSlot(pool_);
|
||||||
if (!slot)
|
if (!slot)
|
||||||
return DeserializationError::NoMemory;
|
return DeserializationError::NoMemory;
|
||||||
|
|
||||||
@@ -377,7 +377,7 @@ class JsonDeserializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DeserializationError::Code parseKey() {
|
DeserializationError::Code parseKey() {
|
||||||
_stringStorage.startString();
|
stringStorage_.startString();
|
||||||
if (isQuote(current())) {
|
if (isQuote(current())) {
|
||||||
return parseQuotedString();
|
return parseQuotedString();
|
||||||
} else {
|
} else {
|
||||||
@@ -388,13 +388,13 @@ class JsonDeserializer {
|
|||||||
DeserializationError::Code parseStringValue(VariantData& variant) {
|
DeserializationError::Code parseStringValue(VariantData& variant) {
|
||||||
DeserializationError::Code err;
|
DeserializationError::Code err;
|
||||||
|
|
||||||
_stringStorage.startString();
|
stringStorage_.startString();
|
||||||
|
|
||||||
err = parseQuotedString();
|
err = parseQuotedString();
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
variant.setString(_stringStorage.save());
|
variant.setString(stringStorage_.save());
|
||||||
|
|
||||||
return DeserializationError::Ok;
|
return DeserializationError::Ok;
|
||||||
}
|
}
|
||||||
@@ -430,9 +430,9 @@ class JsonDeserializer {
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
if (codepoint.append(codeunit))
|
if (codepoint.append(codeunit))
|
||||||
Utf8::encodeCodepoint(codepoint.value(), _stringStorage);
|
Utf8::encodeCodepoint(codepoint.value(), stringStorage_);
|
||||||
#else
|
#else
|
||||||
_stringStorage.append('\\');
|
stringStorage_.append('\\');
|
||||||
#endif
|
#endif
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -444,10 +444,10 @@ class JsonDeserializer {
|
|||||||
move();
|
move();
|
||||||
}
|
}
|
||||||
|
|
||||||
_stringStorage.append(c);
|
stringStorage_.append(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_stringStorage.isValid())
|
if (!stringStorage_.isValid())
|
||||||
return DeserializationError::NoMemory;
|
return DeserializationError::NoMemory;
|
||||||
|
|
||||||
return DeserializationError::Ok;
|
return DeserializationError::Ok;
|
||||||
@@ -460,14 +460,14 @@ class JsonDeserializer {
|
|||||||
if (canBeInNonQuotedString(c)) { // no quotes
|
if (canBeInNonQuotedString(c)) { // no quotes
|
||||||
do {
|
do {
|
||||||
move();
|
move();
|
||||||
_stringStorage.append(c);
|
stringStorage_.append(c);
|
||||||
c = current();
|
c = current();
|
||||||
} while (canBeInNonQuotedString(c));
|
} while (canBeInNonQuotedString(c));
|
||||||
} else {
|
} else {
|
||||||
return DeserializationError::InvalidInput;
|
return DeserializationError::InvalidInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_stringStorage.isValid())
|
if (!stringStorage_.isValid())
|
||||||
return DeserializationError::NoMemory;
|
return DeserializationError::NoMemory;
|
||||||
|
|
||||||
return DeserializationError::Ok;
|
return DeserializationError::Ok;
|
||||||
@@ -516,12 +516,12 @@ class JsonDeserializer {
|
|||||||
char c = current();
|
char c = current();
|
||||||
while (canBeInNumber(c) && n < 63) {
|
while (canBeInNumber(c) && n < 63) {
|
||||||
move();
|
move();
|
||||||
_buffer[n++] = c;
|
buffer_[n++] = c;
|
||||||
c = current();
|
c = current();
|
||||||
}
|
}
|
||||||
_buffer[n] = 0;
|
buffer_[n] = 0;
|
||||||
|
|
||||||
if (!parseNumber(_buffer, result))
|
if (!parseNumber(buffer_, result))
|
||||||
return DeserializationError::InvalidInput;
|
return DeserializationError::InvalidInput;
|
||||||
|
|
||||||
return DeserializationError::Ok;
|
return DeserializationError::Ok;
|
||||||
@@ -585,7 +585,7 @@ class JsonDeserializer {
|
|||||||
switch (current()) {
|
switch (current()) {
|
||||||
// end of string
|
// end of string
|
||||||
case '\0':
|
case '\0':
|
||||||
return _foundSomething ? DeserializationError::IncompleteInput
|
return foundSomething_ ? DeserializationError::IncompleteInput
|
||||||
: DeserializationError::EmptyInput;
|
: DeserializationError::EmptyInput;
|
||||||
|
|
||||||
// spaces
|
// spaces
|
||||||
@@ -640,7 +640,7 @@ class JsonDeserializer {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
_foundSomething = true;
|
foundSomething_ = true;
|
||||||
return DeserializationError::Ok;
|
return DeserializationError::Ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -659,11 +659,11 @@ class JsonDeserializer {
|
|||||||
return DeserializationError::Ok;
|
return DeserializationError::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
TStringStorage _stringStorage;
|
TStringStorage stringStorage_;
|
||||||
bool _foundSomething;
|
bool foundSomething_;
|
||||||
Latch<TReader> _latch;
|
Latch<TReader> latch_;
|
||||||
MemoryPool* _pool;
|
MemoryPool* pool_;
|
||||||
char _buffer[64]; // using a member instead of a local variable because it
|
char buffer_[64]; // using a member instead of a local variable because it
|
||||||
// ended in the recursive path after compiler inlined the
|
// ended in the recursive path after compiler inlined the
|
||||||
// code
|
// code
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class JsonSerializer : public Visitor<size_t> {
|
|||||||
public:
|
public:
|
||||||
static const bool producesText = true;
|
static const bool producesText = true;
|
||||||
|
|
||||||
JsonSerializer(TWriter writer) : _formatter(writer) {}
|
JsonSerializer(TWriter writer) : formatter_(writer) {}
|
||||||
|
|
||||||
FORCE_INLINE size_t visitArray(const CollectionData& array) {
|
FORCE_INLINE size_t visitArray(const CollectionData& array) {
|
||||||
write('[');
|
write('[');
|
||||||
@@ -43,7 +43,7 @@ class JsonSerializer : public Visitor<size_t> {
|
|||||||
const VariantSlot* slot = object.head();
|
const VariantSlot* slot = object.head();
|
||||||
|
|
||||||
while (slot != 0) {
|
while (slot != 0) {
|
||||||
_formatter.writeString(slot->key());
|
formatter_.writeString(slot->key());
|
||||||
write(':');
|
write(':');
|
||||||
slot->data()->accept(*this);
|
slot->data()->accept(*this);
|
||||||
|
|
||||||
@@ -59,60 +59,60 @@ class JsonSerializer : public Visitor<size_t> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t visitFloat(JsonFloat value) {
|
size_t visitFloat(JsonFloat value) {
|
||||||
_formatter.writeFloat(value);
|
formatter_.writeFloat(value);
|
||||||
return bytesWritten();
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t visitString(const char* value) {
|
size_t visitString(const char* value) {
|
||||||
_formatter.writeString(value);
|
formatter_.writeString(value);
|
||||||
return bytesWritten();
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t visitString(const char* value, size_t n) {
|
size_t visitString(const char* value, size_t n) {
|
||||||
_formatter.writeString(value, n);
|
formatter_.writeString(value, n);
|
||||||
return bytesWritten();
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t visitRawJson(const char* data, size_t n) {
|
size_t visitRawJson(const char* data, size_t n) {
|
||||||
_formatter.writeRaw(data, n);
|
formatter_.writeRaw(data, n);
|
||||||
return bytesWritten();
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t visitSignedInteger(JsonInteger value) {
|
size_t visitSignedInteger(JsonInteger value) {
|
||||||
_formatter.writeInteger(value);
|
formatter_.writeInteger(value);
|
||||||
return bytesWritten();
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t visitUnsignedInteger(JsonUInt value) {
|
size_t visitUnsignedInteger(JsonUInt value) {
|
||||||
_formatter.writeInteger(value);
|
formatter_.writeInteger(value);
|
||||||
return bytesWritten();
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t visitBoolean(bool value) {
|
size_t visitBoolean(bool value) {
|
||||||
_formatter.writeBoolean(value);
|
formatter_.writeBoolean(value);
|
||||||
return bytesWritten();
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t visitNull() {
|
size_t visitNull() {
|
||||||
_formatter.writeRaw("null");
|
formatter_.writeRaw("null");
|
||||||
return bytesWritten();
|
return bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t bytesWritten() const {
|
size_t bytesWritten() const {
|
||||||
return _formatter.bytesWritten();
|
return formatter_.bytesWritten();
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(char c) {
|
void write(char c) {
|
||||||
_formatter.writeRaw(c);
|
formatter_.writeRaw(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(const char* s) {
|
void write(const char* s) {
|
||||||
_formatter.writeRaw(s);
|
formatter_.writeRaw(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TextFormatter<TWriter> _formatter;
|
TextFormatter<TWriter> formatter_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -11,45 +11,45 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
|||||||
template <typename TReader>
|
template <typename TReader>
|
||||||
class Latch {
|
class Latch {
|
||||||
public:
|
public:
|
||||||
Latch(TReader reader) : _reader(reader), _loaded(false) {
|
Latch(TReader reader) : reader_(reader), loaded_(false) {
|
||||||
#if ARDUINOJSON_DEBUG
|
#if ARDUINOJSON_DEBUG
|
||||||
_ended = false;
|
ended_ = false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
_loaded = false;
|
loaded_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int last() const {
|
int last() const {
|
||||||
return _current;
|
return current_;
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE char current() {
|
FORCE_INLINE char current() {
|
||||||
if (!_loaded) {
|
if (!loaded_) {
|
||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
return _current;
|
return current_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void load() {
|
void load() {
|
||||||
ARDUINOJSON_ASSERT(!_ended);
|
ARDUINOJSON_ASSERT(!ended_);
|
||||||
int c = _reader.read();
|
int c = reader_.read();
|
||||||
#if ARDUINOJSON_DEBUG
|
#if ARDUINOJSON_DEBUG
|
||||||
if (c <= 0)
|
if (c <= 0)
|
||||||
_ended = true;
|
ended_ = true;
|
||||||
#endif
|
#endif
|
||||||
_current = static_cast<char>(c > 0 ? c : 0);
|
current_ = static_cast<char>(c > 0 ? c : 0);
|
||||||
_loaded = true;
|
loaded_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
TReader _reader;
|
TReader reader_;
|
||||||
char _current; // NOLINT(clang-analyzer-optin.cplusplus.UninitializedObject)
|
char current_; // NOLINT(clang-analyzer-optin.cplusplus.UninitializedObject)
|
||||||
// Not initialized in constructor (+10 bytes on AVR)
|
// Not initialized in constructor (+10 bytes on AVR)
|
||||||
bool _loaded;
|
bool loaded_;
|
||||||
#if ARDUINOJSON_DEBUG
|
#if ARDUINOJSON_DEBUG
|
||||||
bool _ended;
|
bool ended_;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
|
|||||||
typedef JsonSerializer<TWriter> base;
|
typedef JsonSerializer<TWriter> base;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PrettyJsonSerializer(TWriter writer) : base(writer), _nesting(0) {}
|
PrettyJsonSerializer(TWriter writer) : base(writer), nesting_(0) {}
|
||||||
|
|
||||||
size_t visitArray(const CollectionData& array) {
|
size_t visitArray(const CollectionData& array) {
|
||||||
const VariantSlot* slot = array.head();
|
const VariantSlot* slot = array.head();
|
||||||
if (slot) {
|
if (slot) {
|
||||||
base::write("[\r\n");
|
base::write("[\r\n");
|
||||||
_nesting++;
|
nesting_++;
|
||||||
while (slot != 0) {
|
while (slot != 0) {
|
||||||
indent();
|
indent();
|
||||||
slot->data()->accept(*this);
|
slot->data()->accept(*this);
|
||||||
@@ -30,7 +30,7 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
|
|||||||
slot = slot->next();
|
slot = slot->next();
|
||||||
base::write(slot ? ",\r\n" : "\r\n");
|
base::write(slot ? ",\r\n" : "\r\n");
|
||||||
}
|
}
|
||||||
_nesting--;
|
nesting_--;
|
||||||
indent();
|
indent();
|
||||||
base::write("]");
|
base::write("]");
|
||||||
} else {
|
} else {
|
||||||
@@ -43,7 +43,7 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
|
|||||||
const VariantSlot* slot = object.head();
|
const VariantSlot* slot = object.head();
|
||||||
if (slot) {
|
if (slot) {
|
||||||
base::write("{\r\n");
|
base::write("{\r\n");
|
||||||
_nesting++;
|
nesting_++;
|
||||||
while (slot != 0) {
|
while (slot != 0) {
|
||||||
indent();
|
indent();
|
||||||
base::visitString(slot->key());
|
base::visitString(slot->key());
|
||||||
@@ -53,7 +53,7 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
|
|||||||
slot = slot->next();
|
slot = slot->next();
|
||||||
base::write(slot ? ",\r\n" : "\r\n");
|
base::write(slot ? ",\r\n" : "\r\n");
|
||||||
}
|
}
|
||||||
_nesting--;
|
nesting_--;
|
||||||
indent();
|
indent();
|
||||||
base::write("}");
|
base::write("}");
|
||||||
} else {
|
} else {
|
||||||
@@ -64,11 +64,11 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void indent() {
|
void indent() {
|
||||||
for (uint8_t i = 0; i < _nesting; i++)
|
for (uint8_t i = 0; i < nesting_; i++)
|
||||||
base::write(ARDUINOJSON_TAB);
|
base::write(ARDUINOJSON_TAB);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t _nesting;
|
uint8_t nesting_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -20,13 +20,13 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
|||||||
template <typename TWriter>
|
template <typename TWriter>
|
||||||
class TextFormatter {
|
class TextFormatter {
|
||||||
public:
|
public:
|
||||||
explicit TextFormatter(TWriter writer) : _writer(writer) {}
|
explicit TextFormatter(TWriter writer) : writer_(writer) {}
|
||||||
|
|
||||||
TextFormatter& operator=(const TextFormatter&) = delete;
|
TextFormatter& operator=(const TextFormatter&) = delete;
|
||||||
|
|
||||||
// Returns the number of bytes sent to the TWriter implementation.
|
// Returns the number of bytes sent to the TWriter implementation.
|
||||||
size_t bytesWritten() const {
|
size_t bytesWritten() const {
|
||||||
return _writer.count();
|
return writer_.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeBoolean(bool value) {
|
void writeBoolean(bool value) {
|
||||||
@@ -146,28 +146,28 @@ class TextFormatter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void writeRaw(const char* s) {
|
void writeRaw(const char* s) {
|
||||||
_writer.write(reinterpret_cast<const uint8_t*>(s), strlen(s));
|
writer_.write(reinterpret_cast<const uint8_t*>(s), strlen(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeRaw(const char* s, size_t n) {
|
void writeRaw(const char* s, size_t n) {
|
||||||
_writer.write(reinterpret_cast<const uint8_t*>(s), n);
|
writer_.write(reinterpret_cast<const uint8_t*>(s), n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeRaw(const char* begin, const char* end) {
|
void writeRaw(const char* begin, const char* end) {
|
||||||
_writer.write(reinterpret_cast<const uint8_t*>(begin),
|
writer_.write(reinterpret_cast<const uint8_t*>(begin),
|
||||||
static_cast<size_t>(end - begin));
|
static_cast<size_t>(end - begin));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
void writeRaw(const char (&s)[N]) {
|
void writeRaw(const char (&s)[N]) {
|
||||||
_writer.write(reinterpret_cast<const uint8_t*>(s), N - 1);
|
writer_.write(reinterpret_cast<const uint8_t*>(s), N - 1);
|
||||||
}
|
}
|
||||||
void writeRaw(char c) {
|
void writeRaw(char c) {
|
||||||
_writer.write(static_cast<uint8_t>(c));
|
writer_.write(static_cast<uint8_t>(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CountingDecorator<TWriter> _writer;
|
CountingDecorator<TWriter> writer_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -31,31 +31,31 @@ inline bool isLowSurrogate(uint16_t codeunit) {
|
|||||||
|
|
||||||
class Codepoint {
|
class Codepoint {
|
||||||
public:
|
public:
|
||||||
Codepoint() : _highSurrogate(0), _codepoint(0) {}
|
Codepoint() : highSurrogate_(0), codepoint_(0) {}
|
||||||
|
|
||||||
bool append(uint16_t codeunit) {
|
bool append(uint16_t codeunit) {
|
||||||
if (isHighSurrogate(codeunit)) {
|
if (isHighSurrogate(codeunit)) {
|
||||||
_highSurrogate = codeunit & 0x3FF;
|
highSurrogate_ = codeunit & 0x3FF;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLowSurrogate(codeunit)) {
|
if (isLowSurrogate(codeunit)) {
|
||||||
_codepoint =
|
codepoint_ =
|
||||||
uint32_t(0x10000 + ((_highSurrogate << 10) | (codeunit & 0x3FF)));
|
uint32_t(0x10000 + ((highSurrogate_ << 10) | (codeunit & 0x3FF)));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_codepoint = codeunit;
|
codepoint_ = codeunit;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t value() const {
|
uint32_t value() const {
|
||||||
return _codepoint;
|
return codepoint_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint16_t _highSurrogate;
|
uint16_t highSurrogate_;
|
||||||
uint32_t _codepoint;
|
uint32_t codepoint_;
|
||||||
};
|
};
|
||||||
} // namespace Utf16
|
} // namespace Utf16
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -26,43 +26,43 @@
|
|||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
// _begin _end
|
// begin_ end_
|
||||||
// v v
|
// v v
|
||||||
// +-------------+--------------+--------------+
|
// +-------------+--------------+--------------+
|
||||||
// | strings... | (free) | ...variants |
|
// | strings... | (free) | ...variants |
|
||||||
// +-------------+--------------+--------------+
|
// +-------------+--------------+--------------+
|
||||||
// ^ ^
|
// ^ ^
|
||||||
// _left _right
|
// left_ right_
|
||||||
|
|
||||||
class MemoryPool {
|
class MemoryPool {
|
||||||
public:
|
public:
|
||||||
MemoryPool(char* buf, size_t capa)
|
MemoryPool(char* buf, size_t capa)
|
||||||
: _begin(buf),
|
: begin_(buf),
|
||||||
_left(buf),
|
left_(buf),
|
||||||
_right(buf ? buf + capa : 0),
|
right_(buf ? buf + capa : 0),
|
||||||
_end(buf ? buf + capa : 0),
|
end_(buf ? buf + capa : 0),
|
||||||
_overflowed(false) {
|
overflowed_(false) {
|
||||||
ARDUINOJSON_ASSERT(isAligned(_begin));
|
ARDUINOJSON_ASSERT(isAligned(begin_));
|
||||||
ARDUINOJSON_ASSERT(isAligned(_right));
|
ARDUINOJSON_ASSERT(isAligned(right_));
|
||||||
ARDUINOJSON_ASSERT(isAligned(_end));
|
ARDUINOJSON_ASSERT(isAligned(end_));
|
||||||
}
|
}
|
||||||
|
|
||||||
void* buffer() {
|
void* buffer() {
|
||||||
return _begin; // NOLINT(clang-analyzer-unix.Malloc)
|
return begin_; // NOLINT(clang-analyzer-unix.Malloc)
|
||||||
// movePointers() alters this pointer
|
// movePointers() alters this pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the capacity of the memoryPool in bytes
|
// Gets the capacity of the memoryPool in bytes
|
||||||
size_t capacity() const {
|
size_t capacity() const {
|
||||||
return size_t(_end - _begin);
|
return size_t(end_ - begin_);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return size_t(_left - _begin + _end - _right);
|
return size_t(left_ - begin_ + end_ - right_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool overflowed() const {
|
bool overflowed() const {
|
||||||
return _overflowed;
|
return overflowed_;
|
||||||
}
|
}
|
||||||
|
|
||||||
VariantSlot* allocVariant() {
|
VariantSlot* allocVariant() {
|
||||||
@@ -91,40 +91,40 @@ class MemoryPool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void getFreeZone(char** zoneStart, size_t* zoneSize) const {
|
void getFreeZone(char** zoneStart, size_t* zoneSize) const {
|
||||||
*zoneStart = _left;
|
*zoneStart = left_;
|
||||||
*zoneSize = size_t(_right - _left);
|
*zoneSize = size_t(right_ - left_);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* saveStringFromFreeZone(size_t len) {
|
const char* saveStringFromFreeZone(size_t len) {
|
||||||
#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
|
#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
|
||||||
const char* dup = findString(adaptString(_left, len));
|
const char* dup = findString(adaptString(left_, len));
|
||||||
if (dup)
|
if (dup)
|
||||||
return dup;
|
return dup;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char* str = _left;
|
const char* str = left_;
|
||||||
_left += len;
|
left_ += len;
|
||||||
*_left++ = 0;
|
*left_++ = 0;
|
||||||
checkInvariants();
|
checkInvariants();
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
void markAsOverflowed() {
|
void markAsOverflowed() {
|
||||||
_overflowed = true;
|
overflowed_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
_left = _begin;
|
left_ = begin_;
|
||||||
_right = _end;
|
right_ = end_;
|
||||||
_overflowed = false;
|
overflowed_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool canAlloc(size_t bytes) const {
|
bool canAlloc(size_t bytes) const {
|
||||||
return _left + bytes <= _right;
|
return left_ + bytes <= right_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool owns(void* p) const {
|
bool owns(void* p) const {
|
||||||
return _begin <= p && p < _end;
|
return begin_ <= p && p < end_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Workaround for missing placement new
|
// Workaround for missing placement new
|
||||||
@@ -134,51 +134,51 @@ class MemoryPool {
|
|||||||
|
|
||||||
// Squash the free space between strings and variants
|
// Squash the free space between strings and variants
|
||||||
//
|
//
|
||||||
// _begin _end
|
// begin_ end_
|
||||||
// v v
|
// v v
|
||||||
// +-------------+--------------+
|
// +-------------+--------------+
|
||||||
// | strings... | ...variants |
|
// | strings... | ...variants |
|
||||||
// +-------------+--------------+
|
// +-------------+--------------+
|
||||||
// ^
|
// ^
|
||||||
// _left _right
|
// left_ right_
|
||||||
//
|
//
|
||||||
// This funcion is called before a realloc.
|
// This funcion is called before a realloc.
|
||||||
ptrdiff_t squash() {
|
ptrdiff_t squash() {
|
||||||
char* new_right = addPadding(_left);
|
char* new_right = addPadding(left_);
|
||||||
if (new_right >= _right)
|
if (new_right >= right_)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
size_t right_size = static_cast<size_t>(_end - _right);
|
size_t right_size = static_cast<size_t>(end_ - right_);
|
||||||
memmove(new_right, _right, right_size);
|
memmove(new_right, right_, right_size);
|
||||||
|
|
||||||
ptrdiff_t bytes_reclaimed = _right - new_right;
|
ptrdiff_t bytes_reclaimed = right_ - new_right;
|
||||||
_right = new_right;
|
right_ = new_right;
|
||||||
_end = new_right + right_size;
|
end_ = new_right + right_size;
|
||||||
return bytes_reclaimed;
|
return bytes_reclaimed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move all pointers together
|
// Move all pointers together
|
||||||
// This funcion is called after a realloc.
|
// This funcion is called after a realloc.
|
||||||
void movePointers(ptrdiff_t offset) {
|
void movePointers(ptrdiff_t offset) {
|
||||||
_begin += offset;
|
begin_ += offset;
|
||||||
_left += offset;
|
left_ += offset;
|
||||||
_right += offset;
|
right_ += offset;
|
||||||
_end += offset;
|
end_ += offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void checkInvariants() {
|
void checkInvariants() {
|
||||||
ARDUINOJSON_ASSERT(_begin <= _left);
|
ARDUINOJSON_ASSERT(begin_ <= left_);
|
||||||
ARDUINOJSON_ASSERT(_left <= _right);
|
ARDUINOJSON_ASSERT(left_ <= right_);
|
||||||
ARDUINOJSON_ASSERT(_right <= _end);
|
ARDUINOJSON_ASSERT(right_ <= end_);
|
||||||
ARDUINOJSON_ASSERT(isAligned(_right));
|
ARDUINOJSON_ASSERT(isAligned(right_));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
|
#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
const char* findString(const TAdaptedString& str) const {
|
const char* findString(const TAdaptedString& str) const {
|
||||||
size_t n = str.size();
|
size_t n = str.size();
|
||||||
for (char* next = _begin; next + n < _left; ++next) {
|
for (char* next = begin_; next + n < left_; ++next) {
|
||||||
if (next[n] == '\0' && stringEquals(str, adaptString(next, n)))
|
if (next[n] == '\0' && stringEquals(str, adaptString(next, n)))
|
||||||
return next;
|
return next;
|
||||||
|
|
||||||
@@ -192,11 +192,11 @@ class MemoryPool {
|
|||||||
|
|
||||||
char* allocString(size_t n) {
|
char* allocString(size_t n) {
|
||||||
if (!canAlloc(n)) {
|
if (!canAlloc(n)) {
|
||||||
_overflowed = true;
|
overflowed_ = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
char* s = _left;
|
char* s = left_;
|
||||||
_left += n;
|
left_ += n;
|
||||||
checkInvariants();
|
checkInvariants();
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@@ -208,15 +208,15 @@ class MemoryPool {
|
|||||||
|
|
||||||
void* allocRight(size_t bytes) {
|
void* allocRight(size_t bytes) {
|
||||||
if (!canAlloc(bytes)) {
|
if (!canAlloc(bytes)) {
|
||||||
_overflowed = true;
|
overflowed_ = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
_right -= bytes;
|
right_ -= bytes;
|
||||||
return _right;
|
return right_;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *_begin, *_left, *_right, *_end;
|
char *begin_, *left_, *right_, *end_;
|
||||||
bool _overflowed;
|
bool overflowed_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TAdaptedString, typename TCallback>
|
template <typename TAdaptedString, typename TCallback>
|
||||||
|
|||||||
@@ -12,43 +12,43 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
class SerializedValue {
|
class SerializedValue {
|
||||||
public:
|
public:
|
||||||
explicit SerializedValue(T str) : _str(str) {}
|
explicit SerializedValue(T str) : str_(str) {}
|
||||||
operator T() const {
|
operator T() const {
|
||||||
return _str;
|
return str_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* data() const {
|
const char* data() const {
|
||||||
return _str.c_str();
|
return str_.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
// CAUTION: the old Arduino String doesn't have size()
|
// CAUTION: the old Arduino String doesn't have size()
|
||||||
return _str.length();
|
return str_.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T _str;
|
T str_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
class SerializedValue<TChar*> {
|
class SerializedValue<TChar*> {
|
||||||
public:
|
public:
|
||||||
explicit SerializedValue(TChar* p, size_t n) : _data(p), _size(n) {}
|
explicit SerializedValue(TChar* p, size_t n) : data_(p), size_(n) {}
|
||||||
operator TChar*() const {
|
operator TChar*() const {
|
||||||
return _data;
|
return data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
TChar* data() const {
|
TChar* data() const {
|
||||||
return _data;
|
return data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return _size;
|
return size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TChar* _data;
|
TChar* data_;
|
||||||
size_t _size;
|
size_t size_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|||||||
@@ -16,31 +16,34 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
|||||||
template <typename TReader, typename TStringStorage>
|
template <typename TReader, typename TStringStorage>
|
||||||
class MsgPackDeserializer {
|
class MsgPackDeserializer {
|
||||||
public:
|
public:
|
||||||
MsgPackDeserializer(MemoryPool * pool, TReader reader, TStringStorage stringStorage)
|
MsgPackDeserializer(MemoryPool* pool, TReader reader,
|
||||||
: _pool(pool)
|
TStringStorage stringStorage)
|
||||||
, _reader(reader)
|
: pool_(pool),
|
||||||
, _stringStorage(stringStorage)
|
reader_(reader),
|
||||||
, _foundSomething(false) {
|
stringStorage_(stringStorage),
|
||||||
}
|
foundSomething_(false) {}
|
||||||
|
|
||||||
template <typename TFilter>
|
template <typename TFilter>
|
||||||
DeserializationError parse(VariantData & variant, TFilter filter, DeserializationOption::NestingLimit nestingLimit) {
|
DeserializationError parse(VariantData& variant, TFilter filter,
|
||||||
|
DeserializationOption::NestingLimit nestingLimit) {
|
||||||
DeserializationError::Code err;
|
DeserializationError::Code err;
|
||||||
err = parseVariant(&variant, filter, nestingLimit);
|
err = parseVariant(&variant, filter, nestingLimit);
|
||||||
return _foundSomething ? err : DeserializationError::EmptyInput;
|
return foundSomething_ ? err : DeserializationError::EmptyInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename TFilter>
|
template <typename TFilter>
|
||||||
DeserializationError::Code parseVariant(VariantData * variant, TFilter filter, DeserializationOption::NestingLimit nestingLimit) {
|
DeserializationError::Code parseVariant(
|
||||||
|
VariantData* variant, TFilter filter,
|
||||||
|
DeserializationOption::NestingLimit nestingLimit) {
|
||||||
DeserializationError::Code err;
|
DeserializationError::Code err;
|
||||||
|
|
||||||
uint8_t code = 0;
|
uint8_t code = 0; // TODO: why do we need to initialize this variable?
|
||||||
err = readByte(code);
|
err = readByte(code);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
_foundSomething = true;
|
foundSomething_ = true;
|
||||||
|
|
||||||
bool allowValue = filter.allowValue();
|
bool allowValue = filter.allowValue();
|
||||||
|
|
||||||
@@ -220,35 +223,35 @@ class MsgPackDeserializer {
|
|||||||
return DeserializationError::Ok;
|
return DeserializationError::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeserializationError::Code readByte(uint8_t & value) {
|
DeserializationError::Code readByte(uint8_t& value) {
|
||||||
int c = _reader.read();
|
int c = reader_.read();
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
return DeserializationError::IncompleteInput;
|
return DeserializationError::IncompleteInput;
|
||||||
value = static_cast<uint8_t>(c);
|
value = static_cast<uint8_t>(c);
|
||||||
return DeserializationError::Ok;
|
return DeserializationError::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeserializationError::Code readBytes(uint8_t * p, size_t n) {
|
DeserializationError::Code readBytes(uint8_t* p, size_t n) {
|
||||||
if (_reader.readBytes(reinterpret_cast<char *>(p), n) == n)
|
if (reader_.readBytes(reinterpret_cast<char*>(p), n) == n)
|
||||||
return DeserializationError::Ok;
|
return DeserializationError::Ok;
|
||||||
return DeserializationError::IncompleteInput;
|
return DeserializationError::IncompleteInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
DeserializationError::Code readBytes(T & value) {
|
DeserializationError::Code readBytes(T& value) {
|
||||||
return readBytes(reinterpret_cast<uint8_t *>(&value), sizeof(value));
|
return readBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
DeserializationError::Code skipBytes(size_t n) {
|
DeserializationError::Code skipBytes(size_t n) {
|
||||||
for (; n; --n) {
|
for (; n; --n) {
|
||||||
if (_reader.read() < 0)
|
if (reader_.read() < 0)
|
||||||
return DeserializationError::IncompleteInput;
|
return DeserializationError::IncompleteInput;
|
||||||
}
|
}
|
||||||
return DeserializationError::Ok;
|
return DeserializationError::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
DeserializationError::Code readInteger(T & value) {
|
DeserializationError::Code readInteger(T& value) {
|
||||||
DeserializationError::Code err;
|
DeserializationError::Code err;
|
||||||
|
|
||||||
err = readBytes(value);
|
err = readBytes(value);
|
||||||
@@ -261,7 +264,7 @@ class MsgPackDeserializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
DeserializationError::Code readInteger(VariantData * variant) {
|
DeserializationError::Code readInteger(VariantData* variant) {
|
||||||
DeserializationError::Code err;
|
DeserializationError::Code err;
|
||||||
T value;
|
T value;
|
||||||
|
|
||||||
@@ -275,7 +278,8 @@ class MsgPackDeserializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename enable_if<sizeof(T) == 4, DeserializationError::Code>::type readFloat(VariantData * variant) {
|
typename enable_if<sizeof(T) == 4, DeserializationError::Code>::type
|
||||||
|
readFloat(VariantData* variant) {
|
||||||
DeserializationError::Code err;
|
DeserializationError::Code err;
|
||||||
T value;
|
T value;
|
||||||
|
|
||||||
@@ -290,7 +294,8 @@ class MsgPackDeserializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename enable_if<sizeof(T) == 8, DeserializationError::Code>::type readDouble(VariantData * variant) {
|
typename enable_if<sizeof(T) == 8, DeserializationError::Code>::type
|
||||||
|
readDouble(VariantData* variant) {
|
||||||
DeserializationError::Code err;
|
DeserializationError::Code err;
|
||||||
T value;
|
T value;
|
||||||
|
|
||||||
@@ -305,11 +310,12 @@ class MsgPackDeserializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename enable_if<sizeof(T) == 4, DeserializationError::Code>::type readDouble(VariantData * variant) {
|
typename enable_if<sizeof(T) == 4, DeserializationError::Code>::type
|
||||||
|
readDouble(VariantData* variant) {
|
||||||
DeserializationError::Code err;
|
DeserializationError::Code err;
|
||||||
uint8_t i[8]; // input is 8 bytes
|
uint8_t i[8]; // input is 8 bytes
|
||||||
T value; // output is 4 bytes
|
T value; // output is 4 bytes
|
||||||
uint8_t * o = reinterpret_cast<uint8_t *>(&value);
|
uint8_t* o = reinterpret_cast<uint8_t*>(&value);
|
||||||
|
|
||||||
err = readBytes(i, 8);
|
err = readBytes(i, 8);
|
||||||
if (err)
|
if (err)
|
||||||
@@ -323,7 +329,7 @@ class MsgPackDeserializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
DeserializationError::Code readString(VariantData * variant) {
|
DeserializationError::Code readString(VariantData* variant) {
|
||||||
DeserializationError::Code err;
|
DeserializationError::Code err;
|
||||||
T size;
|
T size;
|
||||||
|
|
||||||
@@ -358,21 +364,21 @@ class MsgPackDeserializer {
|
|||||||
return skipBytes(size);
|
return skipBytes(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
DeserializationError::Code readString(VariantData * variant, size_t n) {
|
DeserializationError::Code readString(VariantData* variant, size_t n) {
|
||||||
DeserializationError::Code err;
|
DeserializationError::Code err;
|
||||||
|
|
||||||
err = readString(n);
|
err = readString(n);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
variant->setString(_stringStorage.save());
|
variant->setString(stringStorage_.save());
|
||||||
return DeserializationError::Ok;
|
return DeserializationError::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
DeserializationError::Code readString(size_t n) {
|
DeserializationError::Code readString(size_t n) {
|
||||||
DeserializationError::Code err;
|
DeserializationError::Code err;
|
||||||
|
|
||||||
_stringStorage.startString();
|
stringStorage_.startString();
|
||||||
for (; n; --n) {
|
for (; n; --n) {
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
|
|
||||||
@@ -380,17 +386,19 @@ class MsgPackDeserializer {
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
_stringStorage.append(static_cast<char>(c));
|
stringStorage_.append(static_cast<char>(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_stringStorage.isValid())
|
if (!stringStorage_.isValid())
|
||||||
return DeserializationError::NoMemory;
|
return DeserializationError::NoMemory;
|
||||||
|
|
||||||
return DeserializationError::Ok;
|
return DeserializationError::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TSize, typename TFilter>
|
template <typename TSize, typename TFilter>
|
||||||
DeserializationError::Code readArray(VariantData * variant, TFilter filter, DeserializationOption::NestingLimit nestingLimit) {
|
DeserializationError::Code readArray(
|
||||||
|
VariantData* variant, TFilter filter,
|
||||||
|
DeserializationOption::NestingLimit nestingLimit) {
|
||||||
DeserializationError::Code err;
|
DeserializationError::Code err;
|
||||||
TSize size;
|
TSize size;
|
||||||
|
|
||||||
@@ -402,7 +410,9 @@ class MsgPackDeserializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename TFilter>
|
template <typename TFilter>
|
||||||
DeserializationError::Code readArray(VariantData * variant, size_t n, TFilter filter, DeserializationOption::NestingLimit nestingLimit) {
|
DeserializationError::Code readArray(
|
||||||
|
VariantData* variant, size_t n, TFilter filter,
|
||||||
|
DeserializationOption::NestingLimit nestingLimit) {
|
||||||
DeserializationError::Code err;
|
DeserializationError::Code err;
|
||||||
|
|
||||||
if (nestingLimit.reached())
|
if (nestingLimit.reached())
|
||||||
@@ -410,7 +420,7 @@ class MsgPackDeserializer {
|
|||||||
|
|
||||||
bool allowArray = filter.allowArray();
|
bool allowArray = filter.allowArray();
|
||||||
|
|
||||||
CollectionData * array;
|
CollectionData* array;
|
||||||
if (allowArray) {
|
if (allowArray) {
|
||||||
ARDUINOJSON_ASSERT(variant != 0);
|
ARDUINOJSON_ASSERT(variant != 0);
|
||||||
array = &variant->toArray();
|
array = &variant->toArray();
|
||||||
@@ -421,11 +431,11 @@ class MsgPackDeserializer {
|
|||||||
TFilter memberFilter = filter[0U];
|
TFilter memberFilter = filter[0U];
|
||||||
|
|
||||||
for (; n; --n) {
|
for (; n; --n) {
|
||||||
VariantData * value;
|
VariantData* value;
|
||||||
|
|
||||||
if (memberFilter.allow()) {
|
if (memberFilter.allow()) {
|
||||||
ARDUINOJSON_ASSERT(array != 0);
|
ARDUINOJSON_ASSERT(array != 0);
|
||||||
value = array->addElement(_pool);
|
value = array->addElement(pool_);
|
||||||
if (!value)
|
if (!value)
|
||||||
return DeserializationError::NoMemory;
|
return DeserializationError::NoMemory;
|
||||||
} else {
|
} else {
|
||||||
@@ -441,7 +451,9 @@ class MsgPackDeserializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename TSize, typename TFilter>
|
template <typename TSize, typename TFilter>
|
||||||
DeserializationError::Code readObject(VariantData * variant, TFilter filter, DeserializationOption::NestingLimit nestingLimit) {
|
DeserializationError::Code readObject(
|
||||||
|
VariantData* variant, TFilter filter,
|
||||||
|
DeserializationOption::NestingLimit nestingLimit) {
|
||||||
DeserializationError::Code err;
|
DeserializationError::Code err;
|
||||||
TSize size;
|
TSize size;
|
||||||
|
|
||||||
@@ -453,13 +465,15 @@ class MsgPackDeserializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename TFilter>
|
template <typename TFilter>
|
||||||
DeserializationError::Code readObject(VariantData * variant, size_t n, TFilter filter, DeserializationOption::NestingLimit nestingLimit) {
|
DeserializationError::Code readObject(
|
||||||
|
VariantData* variant, size_t n, TFilter filter,
|
||||||
|
DeserializationOption::NestingLimit nestingLimit) {
|
||||||
DeserializationError::Code err;
|
DeserializationError::Code err;
|
||||||
|
|
||||||
if (nestingLimit.reached())
|
if (nestingLimit.reached())
|
||||||
return DeserializationError::TooDeep;
|
return DeserializationError::TooDeep;
|
||||||
|
|
||||||
CollectionData * object;
|
CollectionData* object;
|
||||||
if (filter.allowObject()) {
|
if (filter.allowObject()) {
|
||||||
ARDUINOJSON_ASSERT(variant != 0);
|
ARDUINOJSON_ASSERT(variant != 0);
|
||||||
object = &variant->toObject();
|
object = &variant->toObject();
|
||||||
@@ -472,18 +486,18 @@ class MsgPackDeserializer {
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
JsonString key = _stringStorage.str();
|
JsonString key = stringStorage_.str();
|
||||||
TFilter memberFilter = filter[key.c_str()];
|
TFilter memberFilter = filter[key.c_str()];
|
||||||
VariantData * member;
|
VariantData* member;
|
||||||
|
|
||||||
if (memberFilter.allow()) {
|
if (memberFilter.allow()) {
|
||||||
ARDUINOJSON_ASSERT(object != 0);
|
ARDUINOJSON_ASSERT(object != 0);
|
||||||
|
|
||||||
// Save key in memory pool.
|
// Save key in memory pool.
|
||||||
// This MUST be done before adding the slot.
|
// This MUST be done before adding the slot.
|
||||||
key = _stringStorage.save();
|
key = stringStorage_.save();
|
||||||
|
|
||||||
VariantSlot * slot = object->addSlot(_pool);
|
VariantSlot* slot = object->addSlot(pool_);
|
||||||
if (!slot)
|
if (!slot)
|
||||||
return DeserializationError::NoMemory;
|
return DeserializationError::NoMemory;
|
||||||
|
|
||||||
@@ -540,10 +554,10 @@ class MsgPackDeserializer {
|
|||||||
return skipBytes(size + 1U);
|
return skipBytes(size + 1U);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryPool * _pool;
|
MemoryPool* pool_;
|
||||||
TReader _reader;
|
TReader reader_;
|
||||||
TStringStorage _stringStorage;
|
TStringStorage stringStorage_;
|
||||||
bool _foundSomething;
|
bool foundSomething_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
@@ -553,7 +567,7 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
|||||||
// Parses a MessagePack input and puts the result in a JsonDocument.
|
// Parses a MessagePack input and puts the result in a JsonDocument.
|
||||||
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
|
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
DeserializationError deserializeMsgPack(JsonDocument & doc, Args &&... args) {
|
DeserializationError deserializeMsgPack(JsonDocument& doc, Args&&... args) {
|
||||||
using namespace detail;
|
using namespace detail;
|
||||||
return deserialize<MsgPackDeserializer>(doc, detail::forward<Args>(args)...);
|
return deserialize<MsgPackDeserializer>(doc, detail::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
@@ -561,9 +575,11 @@ DeserializationError deserializeMsgPack(JsonDocument & doc, Args &&... args) {
|
|||||||
// Parses a MessagePack input and puts the result in a JsonDocument.
|
// Parses a MessagePack input and puts the result in a JsonDocument.
|
||||||
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
|
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
|
||||||
template <typename TChar, typename... Args>
|
template <typename TChar, typename... Args>
|
||||||
DeserializationError deserializeMsgPack(JsonDocument & doc, TChar * input, Args &&... args) {
|
DeserializationError deserializeMsgPack(JsonDocument& doc, TChar* input,
|
||||||
|
Args&&... args) {
|
||||||
using namespace detail;
|
using namespace detail;
|
||||||
return deserialize<MsgPackDeserializer>(doc, input, detail::forward<Args>(args)...);
|
return deserialize<MsgPackDeserializer>(doc, input,
|
||||||
|
detail::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class MsgPackSerializer : public Visitor<size_t> {
|
|||||||
public:
|
public:
|
||||||
static const bool producesText = false;
|
static const bool producesText = false;
|
||||||
|
|
||||||
MsgPackSerializer(TWriter writer) : _writer(writer) {}
|
MsgPackSerializer(TWriter writer) : writer_(writer) {}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename enable_if<sizeof(T) == 4, size_t>::type visitFloat(T value32) {
|
typename enable_if<sizeof(T) == 4, size_t>::type visitFloat(T value32) {
|
||||||
@@ -177,15 +177,15 @@ class MsgPackSerializer : public Visitor<size_t> {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
size_t bytesWritten() const {
|
size_t bytesWritten() const {
|
||||||
return _writer.count();
|
return writer_.count();
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeByte(uint8_t c) {
|
void writeByte(uint8_t c) {
|
||||||
_writer.write(c);
|
writer_.write(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeBytes(const uint8_t* p, size_t n) {
|
void writeBytes(const uint8_t* p, size_t n) {
|
||||||
_writer.write(p, n);
|
writer_.write(p, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -194,7 +194,7 @@ class MsgPackSerializer : public Visitor<size_t> {
|
|||||||
writeBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
|
writeBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
CountingDecorator<TWriter> _writer;
|
CountingDecorator<TWriter> writer_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -146,7 +146,6 @@ inline bool parseNumber(const char* s, VariantData& result) {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
inline T parseNumber(const char* s) {
|
inline T parseNumber(const char* s) {
|
||||||
VariantData value;
|
VariantData value;
|
||||||
value.init(); // VariantData is a POD, so it has no constructor
|
|
||||||
parseNumber(s, value);
|
parseNumber(s, value);
|
||||||
return Converter<T>::fromJson(JsonVariantConst(&value));
|
return Converter<T>::fromJson(JsonVariantConst(&value));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,61 +20,61 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
|
|||||||
typedef JsonObjectIterator iterator;
|
typedef JsonObjectIterator iterator;
|
||||||
|
|
||||||
// Creates an unbound reference.
|
// Creates an unbound reference.
|
||||||
FORCE_INLINE JsonObject() : _data(0), _pool(0) {}
|
FORCE_INLINE JsonObject() : data_(0), pool_(0) {}
|
||||||
|
|
||||||
// INTERNAL USE ONLY
|
// INTERNAL USE ONLY
|
||||||
FORCE_INLINE JsonObject(detail::MemoryPool* buf, detail::CollectionData* data)
|
FORCE_INLINE JsonObject(detail::MemoryPool* buf, detail::CollectionData* data)
|
||||||
: _data(data), _pool(buf) {}
|
: data_(data), pool_(buf) {}
|
||||||
|
|
||||||
operator JsonVariant() const {
|
operator JsonVariant() const {
|
||||||
void* data = _data; // prevent warning cast-align
|
void* data = data_; // prevent warning cast-align
|
||||||
return JsonVariant(_pool, reinterpret_cast<detail::VariantData*>(data));
|
return JsonVariant(pool_, reinterpret_cast<detail::VariantData*>(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
operator JsonObjectConst() const {
|
operator JsonObjectConst() const {
|
||||||
return JsonObjectConst(_data);
|
return JsonObjectConst(data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
operator JsonVariantConst() const {
|
operator JsonVariantConst() const {
|
||||||
return JsonVariantConst(collectionToVariant(_data));
|
return JsonVariantConst(collectionToVariant(data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the reference is unbound.
|
// Returns true if the reference is unbound.
|
||||||
// https://arduinojson.org/v6/api/jsonobject/isnull/
|
// https://arduinojson.org/v6/api/jsonobject/isnull/
|
||||||
FORCE_INLINE bool isNull() const {
|
FORCE_INLINE bool isNull() const {
|
||||||
return _data == 0;
|
return data_ == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the reference is bound.
|
// Returns true if the reference is bound.
|
||||||
// https://arduinojson.org/v6/api/jsonobject/isnull/
|
// https://arduinojson.org/v6/api/jsonobject/isnull/
|
||||||
FORCE_INLINE operator bool() const {
|
FORCE_INLINE operator bool() const {
|
||||||
return _data != 0;
|
return data_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of bytes occupied by the object.
|
// Returns the number of bytes occupied by the object.
|
||||||
// https://arduinojson.org/v6/api/jsonobject/memoryusage/
|
// https://arduinojson.org/v6/api/jsonobject/memoryusage/
|
||||||
FORCE_INLINE size_t memoryUsage() const {
|
FORCE_INLINE size_t memoryUsage() const {
|
||||||
return _data ? _data->memoryUsage() : 0;
|
return data_ ? data_->memoryUsage() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the depth (nesting level) of the object.
|
// Returns the depth (nesting level) of the object.
|
||||||
// https://arduinojson.org/v6/api/jsonobject/nesting/
|
// https://arduinojson.org/v6/api/jsonobject/nesting/
|
||||||
FORCE_INLINE size_t nesting() const {
|
FORCE_INLINE size_t nesting() const {
|
||||||
return variantNesting(collectionToVariant(_data));
|
return variantNesting(collectionToVariant(data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of members in the object.
|
// Returns the number of members in the object.
|
||||||
// https://arduinojson.org/v6/api/jsonobject/size/
|
// https://arduinojson.org/v6/api/jsonobject/size/
|
||||||
FORCE_INLINE size_t size() const {
|
FORCE_INLINE size_t size() const {
|
||||||
return _data ? _data->size() : 0;
|
return data_ ? data_->size() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an iterator to the first key-value pair of the object.
|
// Returns an iterator to the first key-value pair of the object.
|
||||||
// https://arduinojson.org/v6/api/jsonobject/begin/
|
// https://arduinojson.org/v6/api/jsonobject/begin/
|
||||||
FORCE_INLINE iterator begin() const {
|
FORCE_INLINE iterator begin() const {
|
||||||
if (!_data)
|
if (!data_)
|
||||||
return iterator();
|
return iterator();
|
||||||
return iterator(_pool, _data->head());
|
return iterator(pool_, data_->head());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an iterator following the last key-value pair of the object.
|
// Returns an iterator following the last key-value pair of the object.
|
||||||
@@ -87,22 +87,22 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
|
|||||||
// ⚠️ Doesn't release the memory associated with the removed members.
|
// ⚠️ Doesn't release the memory associated with the removed members.
|
||||||
// https://arduinojson.org/v6/api/jsonobject/clear/
|
// https://arduinojson.org/v6/api/jsonobject/clear/
|
||||||
void clear() const {
|
void clear() const {
|
||||||
if (!_data)
|
if (!data_)
|
||||||
return;
|
return;
|
||||||
_data->clear();
|
data_->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copies an object.
|
// Copies an object.
|
||||||
// https://arduinojson.org/v6/api/jsonobject/set/
|
// https://arduinojson.org/v6/api/jsonobject/set/
|
||||||
FORCE_INLINE bool set(JsonObjectConst src) {
|
FORCE_INLINE bool set(JsonObjectConst src) {
|
||||||
if (!_data || !src._data)
|
if (!data_ || !src.data_)
|
||||||
return false;
|
return false;
|
||||||
return _data->copyFrom(*src._data, _pool);
|
return data_->copyFrom(*src.data_, pool_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compares the content of two objects.
|
// Compares the content of two objects.
|
||||||
FORCE_INLINE bool operator==(JsonObject rhs) const {
|
FORCE_INLINE bool operator==(JsonObject rhs) const {
|
||||||
return JsonObjectConst(_data) == JsonObjectConst(rhs._data);
|
return JsonObjectConst(data_) == JsonObjectConst(rhs.data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets or sets the member with specified key.
|
// Gets or sets the member with specified key.
|
||||||
@@ -129,9 +129,9 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
|
|||||||
// ⚠️ Doesn't release the memory associated with the removed member.
|
// ⚠️ Doesn't release the memory associated with the removed member.
|
||||||
// https://arduinojson.org/v6/api/jsonobject/remove/
|
// https://arduinojson.org/v6/api/jsonobject/remove/
|
||||||
FORCE_INLINE void remove(iterator it) const {
|
FORCE_INLINE void remove(iterator it) const {
|
||||||
if (!_data)
|
if (!data_)
|
||||||
return;
|
return;
|
||||||
_data->removeSlot(it._slot);
|
data_->removeSlot(it.slot_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes the member with the specified key.
|
// Removes the member with the specified key.
|
||||||
@@ -194,33 +194,33 @@ class JsonObject : public detail::VariantOperators<JsonObject> {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
detail::MemoryPool* getPool() const {
|
detail::MemoryPool* getPool() const {
|
||||||
return _pool;
|
return pool_;
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::VariantData* getData() const {
|
detail::VariantData* getData() const {
|
||||||
return detail::collectionToVariant(_data);
|
return detail::collectionToVariant(data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::VariantData* getOrCreateData() const {
|
detail::VariantData* getOrCreateData() const {
|
||||||
return detail::collectionToVariant(_data);
|
return detail::collectionToVariant(data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
inline detail::VariantData* getMember(TAdaptedString key) const {
|
inline detail::VariantData* getMember(TAdaptedString key) const {
|
||||||
if (!_data)
|
if (!data_)
|
||||||
return 0;
|
return 0;
|
||||||
return _data->getMember(key);
|
return data_->getMember(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
void removeMember(TAdaptedString key) const {
|
void removeMember(TAdaptedString key) const {
|
||||||
if (!_data)
|
if (!data_)
|
||||||
return;
|
return;
|
||||||
_data->removeMember(key);
|
data_->removeMember(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::CollectionData* _data;
|
detail::CollectionData* data_;
|
||||||
detail::MemoryPool* _pool;
|
detail::MemoryPool* pool_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|||||||
@@ -19,51 +19,51 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
|
|||||||
typedef JsonObjectConstIterator iterator;
|
typedef JsonObjectConstIterator iterator;
|
||||||
|
|
||||||
// Creates an unbound reference.
|
// Creates an unbound reference.
|
||||||
JsonObjectConst() : _data(0) {}
|
JsonObjectConst() : data_(0) {}
|
||||||
|
|
||||||
// INTERNAL USE ONLY
|
// INTERNAL USE ONLY
|
||||||
JsonObjectConst(const detail::CollectionData* data) : _data(data) {}
|
JsonObjectConst(const detail::CollectionData* data) : data_(data) {}
|
||||||
|
|
||||||
operator JsonVariantConst() const {
|
operator JsonVariantConst() const {
|
||||||
return JsonVariantConst(collectionToVariant(_data));
|
return JsonVariantConst(collectionToVariant(data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the reference is unbound.
|
// Returns true if the reference is unbound.
|
||||||
// https://arduinojson.org/v6/api/jsonobjectconst/isnull/
|
// https://arduinojson.org/v6/api/jsonobjectconst/isnull/
|
||||||
FORCE_INLINE bool isNull() const {
|
FORCE_INLINE bool isNull() const {
|
||||||
return _data == 0;
|
return data_ == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the reference is bound.
|
// Returns true if the reference is bound.
|
||||||
// https://arduinojson.org/v6/api/jsonobjectconst/isnull/
|
// https://arduinojson.org/v6/api/jsonobjectconst/isnull/
|
||||||
FORCE_INLINE operator bool() const {
|
FORCE_INLINE operator bool() const {
|
||||||
return _data != 0;
|
return data_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of bytes occupied by the object.
|
// Returns the number of bytes occupied by the object.
|
||||||
// https://arduinojson.org/v6/api/jsonobjectconst/memoryusage/
|
// https://arduinojson.org/v6/api/jsonobjectconst/memoryusage/
|
||||||
FORCE_INLINE size_t memoryUsage() const {
|
FORCE_INLINE size_t memoryUsage() const {
|
||||||
return _data ? _data->memoryUsage() : 0;
|
return data_ ? data_->memoryUsage() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the depth (nesting level) of the object.
|
// Returns the depth (nesting level) of the object.
|
||||||
// https://arduinojson.org/v6/api/jsonobjectconst/nesting/
|
// https://arduinojson.org/v6/api/jsonobjectconst/nesting/
|
||||||
FORCE_INLINE size_t nesting() const {
|
FORCE_INLINE size_t nesting() const {
|
||||||
return variantNesting(collectionToVariant(_data));
|
return variantNesting(collectionToVariant(data_));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of members in the object.
|
// Returns the number of members in the object.
|
||||||
// https://arduinojson.org/v6/api/jsonobjectconst/size/
|
// https://arduinojson.org/v6/api/jsonobjectconst/size/
|
||||||
FORCE_INLINE size_t size() const {
|
FORCE_INLINE size_t size() const {
|
||||||
return _data ? _data->size() : 0;
|
return data_ ? data_->size() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an iterator to the first key-value pair of the object.
|
// Returns an iterator to the first key-value pair of the object.
|
||||||
// https://arduinojson.org/v6/api/jsonobjectconst/begin/
|
// https://arduinojson.org/v6/api/jsonobjectconst/begin/
|
||||||
FORCE_INLINE iterator begin() const {
|
FORCE_INLINE iterator begin() const {
|
||||||
if (!_data)
|
if (!data_)
|
||||||
return iterator();
|
return iterator();
|
||||||
return iterator(_data->head());
|
return iterator(data_->head());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an iterator following the last key-value pair of the object.
|
// Returns an iterator following the last key-value pair of the object.
|
||||||
@@ -106,10 +106,10 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
|
|||||||
|
|
||||||
// Compares objects.
|
// Compares objects.
|
||||||
FORCE_INLINE bool operator==(JsonObjectConst rhs) const {
|
FORCE_INLINE bool operator==(JsonObjectConst rhs) const {
|
||||||
if (_data == rhs._data)
|
if (data_ == rhs.data_)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!_data || !rhs._data)
|
if (!data_ || !rhs.data_)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
@@ -123,17 +123,17 @@ class JsonObjectConst : public detail::VariantOperators<JsonObjectConst> {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
const detail::VariantData* getData() const {
|
const detail::VariantData* getData() const {
|
||||||
return collectionToVariant(_data);
|
return collectionToVariant(data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
const detail::VariantData* getMember(TAdaptedString key) const {
|
const detail::VariantData* getMember(TAdaptedString key) const {
|
||||||
if (!_data)
|
if (!data_)
|
||||||
return 0;
|
return 0;
|
||||||
return _data->getMember(key);
|
return data_->getMember(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
const detail::CollectionData* _data;
|
const detail::CollectionData* data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|||||||
@@ -12,112 +12,112 @@ ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
|
|||||||
class JsonPairPtr {
|
class JsonPairPtr {
|
||||||
public:
|
public:
|
||||||
JsonPairPtr(detail::MemoryPool* pool, detail::VariantSlot* slot)
|
JsonPairPtr(detail::MemoryPool* pool, detail::VariantSlot* slot)
|
||||||
: _pair(pool, slot) {}
|
: pair_(pool, slot) {}
|
||||||
|
|
||||||
const JsonPair* operator->() const {
|
const JsonPair* operator->() const {
|
||||||
return &_pair;
|
return &pair_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const JsonPair& operator*() const {
|
const JsonPair& operator*() const {
|
||||||
return _pair;
|
return pair_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JsonPair _pair;
|
JsonPair pair_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonObjectIterator {
|
class JsonObjectIterator {
|
||||||
friend class JsonObject;
|
friend class JsonObject;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JsonObjectIterator() : _slot(0) {}
|
JsonObjectIterator() : slot_(0) {}
|
||||||
|
|
||||||
explicit JsonObjectIterator(detail::MemoryPool* pool,
|
explicit JsonObjectIterator(detail::MemoryPool* pool,
|
||||||
detail::VariantSlot* slot)
|
detail::VariantSlot* slot)
|
||||||
: _pool(pool), _slot(slot) {}
|
: pool_(pool), slot_(slot) {}
|
||||||
|
|
||||||
JsonPair operator*() const {
|
JsonPair operator*() const {
|
||||||
return JsonPair(_pool, _slot);
|
return JsonPair(pool_, slot_);
|
||||||
}
|
}
|
||||||
JsonPairPtr operator->() {
|
JsonPairPtr operator->() {
|
||||||
return JsonPairPtr(_pool, _slot);
|
return JsonPairPtr(pool_, slot_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const JsonObjectIterator& other) const {
|
bool operator==(const JsonObjectIterator& other) const {
|
||||||
return _slot == other._slot;
|
return slot_ == other.slot_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const JsonObjectIterator& other) const {
|
bool operator!=(const JsonObjectIterator& other) const {
|
||||||
return _slot != other._slot;
|
return slot_ != other.slot_;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObjectIterator& operator++() {
|
JsonObjectIterator& operator++() {
|
||||||
_slot = _slot->next();
|
slot_ = slot_->next();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObjectIterator& operator+=(size_t distance) {
|
JsonObjectIterator& operator+=(size_t distance) {
|
||||||
_slot = _slot->next(distance);
|
slot_ = slot_->next(distance);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
detail::MemoryPool* _pool;
|
detail::MemoryPool* pool_;
|
||||||
detail::VariantSlot* _slot;
|
detail::VariantSlot* slot_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonPairConstPtr {
|
class JsonPairConstPtr {
|
||||||
public:
|
public:
|
||||||
JsonPairConstPtr(const detail::VariantSlot* slot) : _pair(slot) {}
|
JsonPairConstPtr(const detail::VariantSlot* slot) : pair_(slot) {}
|
||||||
|
|
||||||
const JsonPairConst* operator->() const {
|
const JsonPairConst* operator->() const {
|
||||||
return &_pair;
|
return &pair_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const JsonPairConst& operator*() const {
|
const JsonPairConst& operator*() const {
|
||||||
return _pair;
|
return pair_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JsonPairConst _pair;
|
JsonPairConst pair_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonObjectConstIterator {
|
class JsonObjectConstIterator {
|
||||||
friend class JsonObject;
|
friend class JsonObject;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JsonObjectConstIterator() : _slot(0) {}
|
JsonObjectConstIterator() : slot_(0) {}
|
||||||
|
|
||||||
explicit JsonObjectConstIterator(const detail::VariantSlot* slot)
|
explicit JsonObjectConstIterator(const detail::VariantSlot* slot)
|
||||||
: _slot(slot) {}
|
: slot_(slot) {}
|
||||||
|
|
||||||
JsonPairConst operator*() const {
|
JsonPairConst operator*() const {
|
||||||
return JsonPairConst(_slot);
|
return JsonPairConst(slot_);
|
||||||
}
|
}
|
||||||
JsonPairConstPtr operator->() {
|
JsonPairConstPtr operator->() {
|
||||||
return JsonPairConstPtr(_slot);
|
return JsonPairConstPtr(slot_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const JsonObjectConstIterator& other) const {
|
bool operator==(const JsonObjectConstIterator& other) const {
|
||||||
return _slot == other._slot;
|
return slot_ == other.slot_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const JsonObjectConstIterator& other) const {
|
bool operator!=(const JsonObjectConstIterator& other) const {
|
||||||
return _slot != other._slot;
|
return slot_ != other.slot_;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObjectConstIterator& operator++() {
|
JsonObjectConstIterator& operator++() {
|
||||||
_slot = _slot->next();
|
slot_ = slot_->next();
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObjectConstIterator& operator+=(size_t distance) {
|
JsonObjectConstIterator& operator+=(size_t distance) {
|
||||||
_slot = _slot->next(distance);
|
slot_ = slot_->next(distance);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const detail::VariantSlot* _slot;
|
const detail::VariantSlot* slot_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
||||||
|
|||||||
@@ -17,25 +17,25 @@ class JsonPair {
|
|||||||
// INTERNAL USE ONLY
|
// INTERNAL USE ONLY
|
||||||
JsonPair(detail::MemoryPool* pool, detail::VariantSlot* slot) {
|
JsonPair(detail::MemoryPool* pool, detail::VariantSlot* slot) {
|
||||||
if (slot) {
|
if (slot) {
|
||||||
_key = JsonString(slot->key(), slot->ownsKey() ? JsonString::Copied
|
key_ = JsonString(slot->key(), slot->ownsKey() ? JsonString::Copied
|
||||||
: JsonString::Linked);
|
: JsonString::Linked);
|
||||||
_value = JsonVariant(pool, slot->data());
|
value_ = JsonVariant(pool, slot->data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the key.
|
// Returns the key.
|
||||||
JsonString key() const {
|
JsonString key() const {
|
||||||
return _key;
|
return key_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the value.
|
// Returns the value.
|
||||||
JsonVariant value() const {
|
JsonVariant value() const {
|
||||||
return _value;
|
return value_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JsonString _key;
|
JsonString key_;
|
||||||
JsonVariant _value;
|
JsonVariant value_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A read-only key-value pair.
|
// A read-only key-value pair.
|
||||||
@@ -44,25 +44,25 @@ class JsonPairConst {
|
|||||||
public:
|
public:
|
||||||
JsonPairConst(const detail::VariantSlot* slot) {
|
JsonPairConst(const detail::VariantSlot* slot) {
|
||||||
if (slot) {
|
if (slot) {
|
||||||
_key = JsonString(slot->key(), slot->ownsKey() ? JsonString::Copied
|
key_ = JsonString(slot->key(), slot->ownsKey() ? JsonString::Copied
|
||||||
: JsonString::Linked);
|
: JsonString::Linked);
|
||||||
_value = JsonVariantConst(slot->data());
|
value_ = JsonVariantConst(slot->data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the key.
|
// Returns the key.
|
||||||
JsonString key() const {
|
JsonString key() const {
|
||||||
return _key;
|
return key_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the value.
|
// Returns the value.
|
||||||
JsonVariantConst value() const {
|
JsonVariantConst value() const {
|
||||||
return _value;
|
return value_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JsonString _key;
|
JsonString key_;
|
||||||
JsonVariantConst _value;
|
JsonVariantConst value_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ class MemberProxy
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
FORCE_INLINE MemberProxy(TUpstream upstream, TStringRef key)
|
FORCE_INLINE MemberProxy(TUpstream upstream, TStringRef key)
|
||||||
: _upstream(upstream), _key(key) {}
|
: upstream_(upstream), key_(key) {}
|
||||||
|
|
||||||
MemberProxy(const MemberProxy& src)
|
MemberProxy(const MemberProxy& src)
|
||||||
: _upstream(src._upstream), _key(src._key) {}
|
: upstream_(src.upstream_), key_(src.key_) {}
|
||||||
|
|
||||||
FORCE_INLINE MemberProxy& operator=(const MemberProxy& src) {
|
FORCE_INLINE MemberProxy& operator=(const MemberProxy& src) {
|
||||||
this->set(src);
|
this->set(src);
|
||||||
@@ -42,23 +42,23 @@ class MemberProxy
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
FORCE_INLINE MemoryPool* getPool() const {
|
FORCE_INLINE MemoryPool* getPool() const {
|
||||||
return VariantAttorney::getPool(_upstream);
|
return VariantAttorney::getPool(upstream_);
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE VariantData* getData() const {
|
FORCE_INLINE VariantData* getData() const {
|
||||||
return variantGetMember(VariantAttorney::getData(_upstream),
|
return variantGetMember(VariantAttorney::getData(upstream_),
|
||||||
adaptString(_key));
|
adaptString(key_));
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE VariantData* getOrCreateData() const {
|
FORCE_INLINE VariantData* getOrCreateData() const {
|
||||||
return variantGetOrAddMember(VariantAttorney::getOrCreateData(_upstream),
|
return variantGetOrAddMember(VariantAttorney::getOrCreateData(upstream_),
|
||||||
adaptString(_key),
|
adaptString(key_),
|
||||||
VariantAttorney::getPool(_upstream));
|
VariantAttorney::getPool(upstream_));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TUpstream _upstream;
|
TUpstream upstream_;
|
||||||
TStringRef _key;
|
TStringRef key_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -4,7 +4,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Arduino.h>
|
#ifdef ARDUINO
|
||||||
|
# include <Arduino.h>
|
||||||
|
#else
|
||||||
|
// Allow using PROGMEM outside of Arduino (issue #1903)
|
||||||
|
class __FlashStringHelper;
|
||||||
|
# include <avr/pgmspace.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <ArduinoJson/Configuration.hpp>
|
#include <ArduinoJson/Configuration.hpp>
|
||||||
#include <ArduinoJson/Namespace.hpp>
|
#include <ArduinoJson/Namespace.hpp>
|
||||||
|
|||||||
@@ -54,14 +54,14 @@ inline T pgm_read(const T* p) {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
class pgm_ptr {
|
class pgm_ptr {
|
||||||
public:
|
public:
|
||||||
explicit pgm_ptr(const T* ptr) : _ptr(ptr) {}
|
explicit pgm_ptr(const T* ptr) : ptr_(ptr) {}
|
||||||
|
|
||||||
T operator[](intptr_t index) const {
|
T operator[](intptr_t index) const {
|
||||||
return pgm_read(_ptr + index);
|
return pgm_read(ptr_ + index);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const T* _ptr;
|
const T* ptr_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -27,10 +27,10 @@ struct is_convertible {
|
|||||||
static int probe(To);
|
static int probe(To);
|
||||||
static char probe(...);
|
static char probe(...);
|
||||||
|
|
||||||
static From& _from;
|
static From& from_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const bool value = sizeof(probe(_from)) == sizeof(int);
|
static const bool value = sizeof(probe(from_)) == sizeof(int);
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -11,23 +11,23 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
|||||||
template <typename TWriter>
|
template <typename TWriter>
|
||||||
class CountingDecorator {
|
class CountingDecorator {
|
||||||
public:
|
public:
|
||||||
explicit CountingDecorator(TWriter& writer) : _writer(writer), _count(0) {}
|
explicit CountingDecorator(TWriter& writer) : writer_(writer), count_(0) {}
|
||||||
|
|
||||||
void write(uint8_t c) {
|
void write(uint8_t c) {
|
||||||
_count += _writer.write(c);
|
count_ += writer_.write(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(const uint8_t* s, size_t n) {
|
void write(const uint8_t* s, size_t n) {
|
||||||
_count += _writer.write(s, n);
|
count_ += writer_.write(s, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t count() const {
|
size_t count() const {
|
||||||
return _count;
|
return count_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TWriter _writer;
|
TWriter writer_;
|
||||||
size_t _count;
|
size_t count_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -12,18 +12,18 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
|||||||
template <typename TDestination, typename Enable = void>
|
template <typename TDestination, typename Enable = void>
|
||||||
class Writer {
|
class Writer {
|
||||||
public:
|
public:
|
||||||
explicit Writer(TDestination& dest) : _dest(&dest) {}
|
explicit Writer(TDestination& dest) : dest_(&dest) {}
|
||||||
|
|
||||||
size_t write(uint8_t c) {
|
size_t write(uint8_t c) {
|
||||||
return _dest->write(c);
|
return dest_->write(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t write(const uint8_t* s, size_t n) {
|
size_t write(const uint8_t* s, size_t n) {
|
||||||
return _dest->write(s, n);
|
return dest_->write(s, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TDestination* _dest;
|
TDestination* dest_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ class Writer<::String, void> {
|
|||||||
static const size_t bufferCapacity = ARDUINOJSON_STRING_BUFFER_SIZE;
|
static const size_t bufferCapacity = ARDUINOJSON_STRING_BUFFER_SIZE;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Writer(::String& str) : _destination(&str) {
|
explicit Writer(::String& str) : destination_(&str) {
|
||||||
_size = 0;
|
size_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
~Writer() {
|
~Writer() {
|
||||||
@@ -22,10 +22,10 @@ class Writer<::String, void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t write(uint8_t c) {
|
size_t write(uint8_t c) {
|
||||||
if (_size + 1 >= bufferCapacity)
|
if (size_ + 1 >= bufferCapacity)
|
||||||
if (flush() != 0)
|
if (flush() != 0)
|
||||||
return 0;
|
return 0;
|
||||||
_buffer[_size++] = static_cast<char>(c);
|
buffer_[size_++] = static_cast<char>(c);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,17 +37,17 @@ class Writer<::String, void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t flush() {
|
size_t flush() {
|
||||||
ARDUINOJSON_ASSERT(_size < bufferCapacity);
|
ARDUINOJSON_ASSERT(size_ < bufferCapacity);
|
||||||
_buffer[_size] = 0;
|
buffer_[size_] = 0;
|
||||||
if (_destination->concat(_buffer))
|
if (destination_->concat(buffer_))
|
||||||
_size = 0;
|
size_ = 0;
|
||||||
return _size;
|
return size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
::String* _destination;
|
::String* destination_;
|
||||||
char _buffer[bufferCapacity];
|
char buffer_[bufferCapacity];
|
||||||
size_t _size;
|
size_t size_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -13,18 +13,18 @@ class Writer<
|
|||||||
TDestination,
|
TDestination,
|
||||||
typename enable_if<is_base_of<::Print, TDestination>::value>::type> {
|
typename enable_if<is_base_of<::Print, TDestination>::value>::type> {
|
||||||
public:
|
public:
|
||||||
explicit Writer(::Print& print) : _print(&print) {}
|
explicit Writer(::Print& print) : print_(&print) {}
|
||||||
|
|
||||||
size_t write(uint8_t c) {
|
size_t write(uint8_t c) {
|
||||||
return _print->write(c);
|
return print_->write(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t write(const uint8_t* s, size_t n) {
|
size_t write(const uint8_t* s, size_t n) {
|
||||||
return _print->write(s, n);
|
return print_->write(s, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
::Print* _print;
|
::Print* print_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -13,21 +13,21 @@ class Writer<
|
|||||||
TDestination,
|
TDestination,
|
||||||
typename enable_if<is_base_of<std::ostream, TDestination>::value>::type> {
|
typename enable_if<is_base_of<std::ostream, TDestination>::value>::type> {
|
||||||
public:
|
public:
|
||||||
explicit Writer(std::ostream& os) : _os(&os) {}
|
explicit Writer(std::ostream& os) : os_(&os) {}
|
||||||
|
|
||||||
size_t write(uint8_t c) {
|
size_t write(uint8_t c) {
|
||||||
_os->put(static_cast<char>(c));
|
os_->put(static_cast<char>(c));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t write(const uint8_t* s, size_t n) {
|
size_t write(const uint8_t* s, size_t n) {
|
||||||
_os->write(reinterpret_cast<const char*>(s),
|
os_->write(reinterpret_cast<const char*>(s),
|
||||||
static_cast<std::streamsize>(n));
|
static_cast<std::streamsize>(n));
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::ostream* _os;
|
std::ostream* os_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -24,20 +24,20 @@ template <typename TDestination>
|
|||||||
class Writer<TDestination,
|
class Writer<TDestination,
|
||||||
typename enable_if<is_std_string<TDestination>::value>::type> {
|
typename enable_if<is_std_string<TDestination>::value>::type> {
|
||||||
public:
|
public:
|
||||||
Writer(TDestination& str) : _str(&str) {}
|
Writer(TDestination& str) : str_(&str) {}
|
||||||
|
|
||||||
size_t write(uint8_t c) {
|
size_t write(uint8_t c) {
|
||||||
_str->push_back(static_cast<char>(c));
|
str_->push_back(static_cast<char>(c));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t write(const uint8_t* s, size_t n) {
|
size_t write(const uint8_t* s, size_t n) {
|
||||||
_str->append(reinterpret_cast<const char*>(s), n);
|
str_->append(reinterpret_cast<const char*>(s), n);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TDestination* _str;
|
TDestination* str_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -10,19 +10,19 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
|||||||
|
|
||||||
class StringCopier {
|
class StringCopier {
|
||||||
public:
|
public:
|
||||||
StringCopier(MemoryPool* pool) : _pool(pool) {}
|
StringCopier(MemoryPool* pool) : pool_(pool) {}
|
||||||
|
|
||||||
void startString() {
|
void startString() {
|
||||||
_pool->getFreeZone(&_ptr, &_capacity);
|
pool_->getFreeZone(&ptr_, &capacity_);
|
||||||
_size = 0;
|
size_ = 0;
|
||||||
if (_capacity == 0)
|
if (capacity_ == 0)
|
||||||
_pool->markAsOverflowed();
|
pool_->markAsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonString save() {
|
JsonString save() {
|
||||||
ARDUINOJSON_ASSERT(_ptr);
|
ARDUINOJSON_ASSERT(ptr_);
|
||||||
ARDUINOJSON_ASSERT(_size < _capacity); // needs room for the terminator
|
ARDUINOJSON_ASSERT(size_ < capacity_); // needs room for the terminator
|
||||||
return JsonString(_pool->saveStringFromFreeZone(_size), _size,
|
return JsonString(pool_->saveStringFromFreeZone(size_), size_,
|
||||||
JsonString::Copied);
|
JsonString::Copied);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,36 +37,36 @@ class StringCopier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void append(char c) {
|
void append(char c) {
|
||||||
if (_size + 1 < _capacity)
|
if (size_ + 1 < capacity_)
|
||||||
_ptr[_size++] = c;
|
ptr_[size_++] = c;
|
||||||
else
|
else
|
||||||
_pool->markAsOverflowed();
|
pool_->markAsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isValid() const {
|
bool isValid() const {
|
||||||
return !_pool->overflowed();
|
return !pool_->overflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return _size;
|
return size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonString str() const {
|
JsonString str() const {
|
||||||
ARDUINOJSON_ASSERT(_ptr);
|
ARDUINOJSON_ASSERT(ptr_);
|
||||||
ARDUINOJSON_ASSERT(_size < _capacity);
|
ARDUINOJSON_ASSERT(size_ < capacity_);
|
||||||
_ptr[_size] = 0;
|
ptr_[size_] = 0;
|
||||||
return JsonString(_ptr, _size, JsonString::Copied);
|
return JsonString(ptr_, size_, JsonString::Copied);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MemoryPool* _pool;
|
MemoryPool* pool_;
|
||||||
|
|
||||||
// These fields aren't initialized by the constructor but startString()
|
// These fields aren't initialized by the constructor but startString()
|
||||||
//
|
//
|
||||||
// NOLINTNEXTLINE(clang-analyzer-optin.cplusplus.UninitializedObject)
|
// NOLINTNEXTLINE(clang-analyzer-optin.cplusplus.UninitializedObject)
|
||||||
char* _ptr;
|
char* ptr_;
|
||||||
// NOLINTNEXTLINE(clang-analyzer-optin.cplusplus.UninitializedObject)
|
// NOLINTNEXTLINE(clang-analyzer-optin.cplusplus.UninitializedObject)
|
||||||
size_t _size, _capacity;
|
size_t size_, capacity_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -11,20 +11,20 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
|||||||
|
|
||||||
class StringMover {
|
class StringMover {
|
||||||
public:
|
public:
|
||||||
StringMover(char* ptr) : _writePtr(ptr) {}
|
StringMover(char* ptr) : writePtr_(ptr) {}
|
||||||
|
|
||||||
void startString() {
|
void startString() {
|
||||||
_startPtr = _writePtr;
|
startPtr_ = writePtr_;
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE JsonString save() {
|
FORCE_INLINE JsonString save() {
|
||||||
JsonString s = str();
|
JsonString s = str();
|
||||||
_writePtr++;
|
writePtr_++;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(char c) {
|
void append(char c) {
|
||||||
*_writePtr++ = c;
|
*writePtr_++ = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isValid() const {
|
bool isValid() const {
|
||||||
@@ -32,17 +32,17 @@ class StringMover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JsonString str() const {
|
JsonString str() const {
|
||||||
_writePtr[0] = 0; // terminator
|
writePtr_[0] = 0; // terminator
|
||||||
return JsonString(_startPtr, size(), JsonString::Linked);
|
return JsonString(startPtr_, size(), JsonString::Linked);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return size_t(_writePtr - _startPtr);
|
return size_t(writePtr_ - startPtr_);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char* _writePtr;
|
char* writePtr_;
|
||||||
char* _startPtr;
|
char* startPtr_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Arduino.h>
|
|
||||||
|
|
||||||
#include <ArduinoJson/Polyfills/pgmspace.hpp>
|
#include <ArduinoJson/Polyfills/pgmspace.hpp>
|
||||||
#include <ArduinoJson/Strings/StringAdapter.hpp>
|
#include <ArduinoJson/Strings/StringAdapter.hpp>
|
||||||
|
|
||||||
@@ -16,20 +14,20 @@ class FlashString {
|
|||||||
static const size_t typeSortKey = 1;
|
static const size_t typeSortKey = 1;
|
||||||
|
|
||||||
FlashString(const __FlashStringHelper* str, size_t sz)
|
FlashString(const __FlashStringHelper* str, size_t sz)
|
||||||
: _str(reinterpret_cast<const char*>(str)), _size(sz) {}
|
: str_(reinterpret_cast<const char*>(str)), size_(sz) {}
|
||||||
|
|
||||||
bool isNull() const {
|
bool isNull() const {
|
||||||
return !_str;
|
return !str_;
|
||||||
}
|
}
|
||||||
|
|
||||||
char operator[](size_t i) const {
|
char operator[](size_t i) const {
|
||||||
ARDUINOJSON_ASSERT(_str != 0);
|
ARDUINOJSON_ASSERT(str_ != 0);
|
||||||
ARDUINOJSON_ASSERT(i <= _size);
|
ARDUINOJSON_ASSERT(i <= size_);
|
||||||
return static_cast<char>(pgm_read_byte(_str + i));
|
return static_cast<char>(pgm_read_byte(str_ + i));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return _size;
|
return size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool stringEquals(FlashString a, SizedRamString b) {
|
friend bool stringEquals(FlashString a, SizedRamString b) {
|
||||||
@@ -38,7 +36,7 @@ class FlashString {
|
|||||||
ARDUINOJSON_ASSERT(!b.isNull());
|
ARDUINOJSON_ASSERT(!b.isNull());
|
||||||
if (a.size() != b.size())
|
if (a.size() != b.size())
|
||||||
return false;
|
return false;
|
||||||
return ::memcmp_P(b.data(), a._str, a._size) == 0;
|
return ::memcmp_P(b.data(), a.str_, a.size_) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend int stringCompare(FlashString a, SizedRamString b) {
|
friend int stringCompare(FlashString a, SizedRamString b) {
|
||||||
@@ -46,7 +44,7 @@ class FlashString {
|
|||||||
ARDUINOJSON_ASSERT(!a.isNull());
|
ARDUINOJSON_ASSERT(!a.isNull());
|
||||||
ARDUINOJSON_ASSERT(!b.isNull());
|
ARDUINOJSON_ASSERT(!b.isNull());
|
||||||
size_t minsize = a.size() < b.size() ? a.size() : b.size();
|
size_t minsize = a.size() < b.size() ? a.size() : b.size();
|
||||||
int res = ::memcmp_P(b.data(), a._str, minsize);
|
int res = ::memcmp_P(b.data(), a.str_, minsize);
|
||||||
if (res)
|
if (res)
|
||||||
return -res;
|
return -res;
|
||||||
if (a.size() < b.size())
|
if (a.size() < b.size())
|
||||||
@@ -58,7 +56,7 @@ class FlashString {
|
|||||||
|
|
||||||
friend void stringGetChars(FlashString s, char* p, size_t n) {
|
friend void stringGetChars(FlashString s, char* p, size_t n) {
|
||||||
ARDUINOJSON_ASSERT(s.size() <= n);
|
ARDUINOJSON_ASSERT(s.size() <= n);
|
||||||
::memcpy_P(p, s._str, n);
|
::memcpy_P(p, s.str_, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringStoragePolicy::Copy storagePolicy() const {
|
StringStoragePolicy::Copy storagePolicy() const {
|
||||||
@@ -66,8 +64,8 @@ class FlashString {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char* _str;
|
const char* str_;
|
||||||
size_t _size;
|
size_t size_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|||||||
@@ -13,15 +13,15 @@ ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
|||||||
class JsonStringAdapter : public SizedRamString {
|
class JsonStringAdapter : public SizedRamString {
|
||||||
public:
|
public:
|
||||||
JsonStringAdapter(const JsonString& s)
|
JsonStringAdapter(const JsonString& s)
|
||||||
: SizedRamString(s.c_str(), s.size()), _linked(s.isLinked()) {}
|
: SizedRamString(s.c_str(), s.size()), linked_(s.isLinked()) {}
|
||||||
|
|
||||||
StringStoragePolicy::LinkOrCopy storagePolicy() const {
|
StringStoragePolicy::LinkOrCopy storagePolicy() const {
|
||||||
StringStoragePolicy::LinkOrCopy policy = {_linked};
|
StringStoragePolicy::LinkOrCopy policy = {linked_};
|
||||||
return policy;
|
return policy;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _linked;
|
bool linked_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|||||||
@@ -21,31 +21,31 @@ class ZeroTerminatedRamString {
|
|||||||
public:
|
public:
|
||||||
static const size_t typeSortKey = 3;
|
static const size_t typeSortKey = 3;
|
||||||
|
|
||||||
ZeroTerminatedRamString(const char* str) : _str(str) {}
|
ZeroTerminatedRamString(const char* str) : str_(str) {}
|
||||||
|
|
||||||
bool isNull() const {
|
bool isNull() const {
|
||||||
return !_str;
|
return !str_;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return _str ? ::strlen(_str) : 0;
|
return str_ ? ::strlen(str_) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
char operator[](size_t i) const {
|
char operator[](size_t i) const {
|
||||||
ARDUINOJSON_ASSERT(_str != 0);
|
ARDUINOJSON_ASSERT(str_ != 0);
|
||||||
ARDUINOJSON_ASSERT(i <= size());
|
ARDUINOJSON_ASSERT(i <= size());
|
||||||
return _str[i];
|
return str_[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* data() const {
|
const char* data() const {
|
||||||
return _str;
|
return str_;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend int stringCompare(ZeroTerminatedRamString a,
|
friend int stringCompare(ZeroTerminatedRamString a,
|
||||||
ZeroTerminatedRamString b) {
|
ZeroTerminatedRamString b) {
|
||||||
ARDUINOJSON_ASSERT(!a.isNull());
|
ARDUINOJSON_ASSERT(!a.isNull());
|
||||||
ARDUINOJSON_ASSERT(!b.isNull());
|
ARDUINOJSON_ASSERT(!b.isNull());
|
||||||
return ::strcmp(a._str, b._str);
|
return ::strcmp(a.str_, b.str_);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool stringEquals(ZeroTerminatedRamString a,
|
friend bool stringEquals(ZeroTerminatedRamString a,
|
||||||
@@ -58,7 +58,7 @@ class ZeroTerminatedRamString {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const char* _str;
|
const char* str_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
@@ -101,24 +101,24 @@ class SizedRamString {
|
|||||||
public:
|
public:
|
||||||
static const size_t typeSortKey = 2;
|
static const size_t typeSortKey = 2;
|
||||||
|
|
||||||
SizedRamString(const char* str, size_t sz) : _str(str), _size(sz) {}
|
SizedRamString(const char* str, size_t sz) : str_(str), size_(sz) {}
|
||||||
|
|
||||||
bool isNull() const {
|
bool isNull() const {
|
||||||
return !_str;
|
return !str_;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return _size;
|
return size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
char operator[](size_t i) const {
|
char operator[](size_t i) const {
|
||||||
ARDUINOJSON_ASSERT(_str != 0);
|
ARDUINOJSON_ASSERT(str_ != 0);
|
||||||
ARDUINOJSON_ASSERT(i <= size());
|
ARDUINOJSON_ASSERT(i <= size());
|
||||||
return _str[i];
|
return str_[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* data() const {
|
const char* data() const {
|
||||||
return _str;
|
return str_;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringStoragePolicy::Copy storagePolicy() const {
|
StringStoragePolicy::Copy storagePolicy() const {
|
||||||
@@ -126,8 +126,8 @@ class SizedRamString {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const char* _str;
|
const char* str_;
|
||||||
size_t _size;
|
size_t size_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TChar>
|
template <typename TChar>
|
||||||
|
|||||||
@@ -16,51 +16,51 @@ class JsonString {
|
|||||||
public:
|
public:
|
||||||
enum Ownership { Copied, Linked };
|
enum Ownership { Copied, Linked };
|
||||||
|
|
||||||
JsonString() : _data(0), _size(0), _ownership(Linked) {}
|
JsonString() : data_(0), size_(0), ownership_(Linked) {}
|
||||||
|
|
||||||
JsonString(const char* data, Ownership ownership = Linked)
|
JsonString(const char* data, Ownership ownership = Linked)
|
||||||
: _data(data), _size(data ? ::strlen(data) : 0), _ownership(ownership) {}
|
: data_(data), size_(data ? ::strlen(data) : 0), ownership_(ownership) {}
|
||||||
|
|
||||||
JsonString(const char* data, size_t sz, Ownership ownership = Linked)
|
JsonString(const char* data, size_t sz, Ownership ownership = Linked)
|
||||||
: _data(data), _size(sz), _ownership(ownership) {}
|
: data_(data), size_(sz), ownership_(ownership) {}
|
||||||
|
|
||||||
// Returns a pointer to the characters.
|
// Returns a pointer to the characters.
|
||||||
const char* c_str() const {
|
const char* c_str() const {
|
||||||
return _data;
|
return data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the string is null.
|
// Returns true if the string is null.
|
||||||
bool isNull() const {
|
bool isNull() const {
|
||||||
return !_data;
|
return !data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the string is stored by address.
|
// Returns true if the string is stored by address.
|
||||||
// Returns false if the string is stored by copy.
|
// Returns false if the string is stored by copy.
|
||||||
bool isLinked() const {
|
bool isLinked() const {
|
||||||
return _ownership == Linked;
|
return ownership_ == Linked;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns length of the string.
|
// Returns length of the string.
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return _size;
|
return size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the string is non-null
|
// Returns true if the string is non-null
|
||||||
explicit operator bool() const {
|
explicit operator bool() const {
|
||||||
return _data != 0;
|
return data_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if strings are equal.
|
// Returns true if strings are equal.
|
||||||
friend bool operator==(JsonString lhs, JsonString rhs) {
|
friend bool operator==(JsonString lhs, JsonString rhs) {
|
||||||
if (lhs._size != rhs._size)
|
if (lhs.size_ != rhs.size_)
|
||||||
return false;
|
return false;
|
||||||
if (lhs._data == rhs._data)
|
if (lhs.data_ == rhs.data_)
|
||||||
return true;
|
return true;
|
||||||
if (!lhs._data)
|
if (!lhs.data_)
|
||||||
return false;
|
return false;
|
||||||
if (!rhs._data)
|
if (!rhs.data_)
|
||||||
return false;
|
return false;
|
||||||
return memcmp(lhs._data, rhs._data, lhs._size) == 0;
|
return memcmp(lhs.data_, rhs.data_, lhs.size_) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if strings differs.
|
// Returns true if strings differs.
|
||||||
@@ -76,9 +76,9 @@ class JsonString {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char* _data;
|
const char* data_;
|
||||||
size_t _size;
|
size_t size_;
|
||||||
Ownership _ownership;
|
Ownership ownership_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
||||||
|
|||||||
@@ -205,43 +205,43 @@ struct Converter<decltype(nullptr)> : private detail::VariantAttorney {
|
|||||||
namespace detail {
|
namespace detail {
|
||||||
class MemoryPoolPrint : public Print {
|
class MemoryPoolPrint : public Print {
|
||||||
public:
|
public:
|
||||||
MemoryPoolPrint(MemoryPool* pool) : _pool(pool), _size(0) {
|
MemoryPoolPrint(MemoryPool* pool) : pool_(pool), size_(0) {
|
||||||
pool->getFreeZone(&_string, &_capacity);
|
pool->getFreeZone(&string_, &capacity_);
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonString str() {
|
JsonString str() {
|
||||||
ARDUINOJSON_ASSERT(_size < _capacity);
|
ARDUINOJSON_ASSERT(size_ < capacity_);
|
||||||
return JsonString(_pool->saveStringFromFreeZone(_size), _size,
|
return JsonString(pool_->saveStringFromFreeZone(size_), size_,
|
||||||
JsonString::Copied);
|
JsonString::Copied);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t write(uint8_t c) {
|
size_t write(uint8_t c) {
|
||||||
if (_size >= _capacity)
|
if (size_ >= capacity_)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
_string[_size++] = char(c);
|
string_[size_++] = char(c);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t write(const uint8_t* buffer, size_t size) {
|
size_t write(const uint8_t* buffer, size_t size) {
|
||||||
if (_size + size >= _capacity) {
|
if (size_ + size >= capacity_) {
|
||||||
_size = _capacity; // mark as overflowed
|
size_ = capacity_; // mark as overflowed
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memcpy(&_string[_size], buffer, size);
|
memcpy(&string_[size_], buffer, size);
|
||||||
_size += size;
|
size_ += size;
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool overflowed() const {
|
bool overflowed() const {
|
||||||
return _size >= _capacity;
|
return size_ >= capacity_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MemoryPool* _pool;
|
MemoryPool* pool_;
|
||||||
size_t _size;
|
size_t size_;
|
||||||
char* _string;
|
char* string_;
|
||||||
size_t _capacity;
|
size_t capacity_;
|
||||||
};
|
};
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
|
|||||||
@@ -16,27 +16,27 @@ class JsonVariant : public detail::VariantRefBase<JsonVariant>,
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// Creates an unbound reference.
|
// Creates an unbound reference.
|
||||||
JsonVariant() : _data(0), _pool(0) {}
|
JsonVariant() : data_(0), pool_(0) {}
|
||||||
|
|
||||||
// INTERNAL USE ONLY
|
// INTERNAL USE ONLY
|
||||||
JsonVariant(detail::MemoryPool* pool, detail::VariantData* data)
|
JsonVariant(detail::MemoryPool* pool, detail::VariantData* data)
|
||||||
: _data(data), _pool(pool) {}
|
: data_(data), pool_(pool) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FORCE_INLINE detail::MemoryPool* getPool() const {
|
FORCE_INLINE detail::MemoryPool* getPool() const {
|
||||||
return _pool;
|
return pool_;
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE detail::VariantData* getData() const {
|
FORCE_INLINE detail::VariantData* getData() const {
|
||||||
return _data;
|
return data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE detail::VariantData* getOrCreateData() const {
|
FORCE_INLINE detail::VariantData* getOrCreateData() const {
|
||||||
return _data;
|
return data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::VariantData* _data;
|
detail::VariantData* data_;
|
||||||
detail::MemoryPool* _pool;
|
detail::MemoryPool* pool_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
|
|||||||
@@ -30,39 +30,39 @@ class JsonVariantConst : public detail::VariantTag,
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// Creates an unbound reference.
|
// Creates an unbound reference.
|
||||||
JsonVariantConst() : _data(0) {}
|
JsonVariantConst() : data_(0) {}
|
||||||
|
|
||||||
// INTERNAL USE ONLY
|
// INTERNAL USE ONLY
|
||||||
explicit JsonVariantConst(const detail::VariantData* data) : _data(data) {}
|
explicit JsonVariantConst(const detail::VariantData* data) : data_(data) {}
|
||||||
|
|
||||||
// Returns true if the value is null or the reference is unbound.
|
// Returns true if the value is null or the reference is unbound.
|
||||||
// https://arduinojson.org/v6/api/jsonvariantconst/isnull/
|
// https://arduinojson.org/v6/api/jsonvariantconst/isnull/
|
||||||
FORCE_INLINE bool isNull() const {
|
FORCE_INLINE bool isNull() const {
|
||||||
using namespace detail;
|
using namespace detail;
|
||||||
return variantIsNull(_data);
|
return variantIsNull(data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the reference is unbound.
|
// Returns true if the reference is unbound.
|
||||||
FORCE_INLINE bool isUnbound() const {
|
FORCE_INLINE bool isUnbound() const {
|
||||||
return !_data;
|
return !data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the number of bytes occupied by the value.
|
// Returns the number of bytes occupied by the value.
|
||||||
// https://arduinojson.org/v6/api/jsonvariantconst/memoryusage/
|
// https://arduinojson.org/v6/api/jsonvariantconst/memoryusage/
|
||||||
FORCE_INLINE size_t memoryUsage() const {
|
FORCE_INLINE size_t memoryUsage() const {
|
||||||
return _data ? _data->memoryUsage() : 0;
|
return data_ ? data_->memoryUsage() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the depth (nesting level) of the value.
|
// Returns the depth (nesting level) of the value.
|
||||||
// https://arduinojson.org/v6/api/jsonvariantconst/nesting/
|
// https://arduinojson.org/v6/api/jsonvariantconst/nesting/
|
||||||
FORCE_INLINE size_t nesting() const {
|
FORCE_INLINE size_t nesting() const {
|
||||||
return variantNesting(_data);
|
return variantNesting(data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the size of the array or object.
|
// Returns the size of the array or object.
|
||||||
// https://arduinojson.org/v6/api/jsonvariantconst/size/
|
// https://arduinojson.org/v6/api/jsonvariantconst/size/
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return variantSize(_data);
|
return variantSize(data_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Casts the value to the specified type.
|
// Casts the value to the specified type.
|
||||||
@@ -93,7 +93,7 @@ class JsonVariantConst : public detail::VariantTag,
|
|||||||
// Gets array's element at specified index.
|
// Gets array's element at specified index.
|
||||||
// https://arduinojson.org/v6/api/jsonvariantconst/subscript/
|
// https://arduinojson.org/v6/api/jsonvariantconst/subscript/
|
||||||
FORCE_INLINE JsonVariantConst operator[](size_t index) const {
|
FORCE_INLINE JsonVariantConst operator[](size_t index) const {
|
||||||
return JsonVariantConst(variantGetElement(_data, index));
|
return JsonVariantConst(variantGetElement(data_, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets object's member with specified key.
|
// Gets object's member with specified key.
|
||||||
@@ -102,7 +102,7 @@ class JsonVariantConst : public detail::VariantTag,
|
|||||||
FORCE_INLINE typename detail::enable_if<detail::IsString<TString>::value,
|
FORCE_INLINE typename detail::enable_if<detail::IsString<TString>::value,
|
||||||
JsonVariantConst>::type
|
JsonVariantConst>::type
|
||||||
operator[](const TString& key) const {
|
operator[](const TString& key) const {
|
||||||
return JsonVariantConst(variantGetMember(_data, detail::adaptString(key)));
|
return JsonVariantConst(variantGetMember(data_, detail::adaptString(key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets object's member with specified key.
|
// Gets object's member with specified key.
|
||||||
@@ -111,7 +111,7 @@ class JsonVariantConst : public detail::VariantTag,
|
|||||||
FORCE_INLINE typename detail::enable_if<detail::IsString<TChar*>::value,
|
FORCE_INLINE typename detail::enable_if<detail::IsString<TChar*>::value,
|
||||||
JsonVariantConst>::type
|
JsonVariantConst>::type
|
||||||
operator[](TChar* key) const {
|
operator[](TChar* key) const {
|
||||||
return JsonVariantConst(variantGetMember(_data, detail::adaptString(key)));
|
return JsonVariantConst(variantGetMember(data_, detail::adaptString(key)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if tge object contains the specified key.
|
// Returns true if tge object contains the specified key.
|
||||||
@@ -134,11 +134,11 @@ class JsonVariantConst : public detail::VariantTag,
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
const detail::VariantData* getData() const {
|
const detail::VariantData* getData() const {
|
||||||
return _data;
|
return data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const detail::VariantData* _data;
|
const detail::VariantData* data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
ARDUINOJSON_END_PUBLIC_NAMESPACE
|
||||||
|
|||||||
@@ -10,17 +10,17 @@
|
|||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
struct SlotKeySetter {
|
struct SlotKeySetter {
|
||||||
SlotKeySetter(VariantSlot* instance) : _instance(instance) {}
|
SlotKeySetter(VariantSlot* instance) : instance_(instance) {}
|
||||||
|
|
||||||
template <typename TStoredString>
|
template <typename TStoredString>
|
||||||
void operator()(TStoredString s) {
|
void operator()(TStoredString s) {
|
||||||
if (!s)
|
if (!s)
|
||||||
return;
|
return;
|
||||||
ARDUINOJSON_ASSERT(_instance != 0);
|
ARDUINOJSON_ASSERT(instance_ != 0);
|
||||||
_instance->setKey(s);
|
instance_->setKey(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
VariantSlot* _instance;
|
VariantSlot* instance_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
|
|||||||
@@ -20,14 +20,13 @@ template <typename T, typename Enable = void>
|
|||||||
struct Comparer;
|
struct Comparer;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct Comparer<T, typename enable_if<IsString<T>::value>::type> : ComparerBase {
|
struct Comparer<T, typename enable_if<IsString<T>::value>::type>
|
||||||
T rhs;
|
: ComparerBase {
|
||||||
|
T rhs; // TODO: store adapted string?
|
||||||
|
|
||||||
explicit Comparer(T value)
|
explicit Comparer(T value) : rhs(value) {}
|
||||||
: rhs(value) {
|
|
||||||
}
|
|
||||||
|
|
||||||
CompareResult visitString(const char * lhs, size_t n) {
|
CompareResult visitString(const char* lhs, size_t n) {
|
||||||
int i = stringCompare(adaptString(rhs), adaptString(lhs, n));
|
int i = stringCompare(adaptString(rhs), adaptString(lhs, n));
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
return COMPARE_RESULT_GREATER;
|
return COMPARE_RESULT_GREATER;
|
||||||
@@ -46,12 +45,12 @@ struct Comparer<T, typename enable_if<IsString<T>::value>::type> : ComparerBase
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct Comparer<T, typename enable_if<is_integral<T>::value || is_floating_point<T>::value>::type> : ComparerBase {
|
struct Comparer<T, typename enable_if<is_integral<T>::value ||
|
||||||
|
is_floating_point<T>::value>::type>
|
||||||
|
: ComparerBase {
|
||||||
T rhs;
|
T rhs;
|
||||||
|
|
||||||
explicit Comparer(T value)
|
explicit Comparer(T value) : rhs(value) {}
|
||||||
: rhs(value) {
|
|
||||||
}
|
|
||||||
|
|
||||||
CompareResult visitFloat(JsonFloat lhs) {
|
CompareResult visitFloat(JsonFloat lhs) {
|
||||||
return arithmeticCompare(lhs, rhs);
|
return arithmeticCompare(lhs, rhs);
|
||||||
@@ -78,20 +77,16 @@ struct NullComparer : ComparerBase {
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct Comparer<decltype(nullptr), void> : NullComparer {
|
struct Comparer<decltype(nullptr), void> : NullComparer {
|
||||||
explicit Comparer(decltype(nullptr))
|
explicit Comparer(decltype(nullptr)) : NullComparer() {}
|
||||||
: NullComparer() {
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ArrayComparer : ComparerBase {
|
struct ArrayComparer : ComparerBase {
|
||||||
const CollectionData * _rhs;
|
const CollectionData* rhs_;
|
||||||
|
|
||||||
explicit ArrayComparer(const CollectionData & rhs)
|
explicit ArrayComparer(const CollectionData& rhs) : rhs_(&rhs) {}
|
||||||
: _rhs(&rhs) {
|
|
||||||
}
|
|
||||||
|
|
||||||
CompareResult visitArray(const CollectionData & lhs) {
|
CompareResult visitArray(const CollectionData& lhs) {
|
||||||
if (JsonArrayConst(&lhs) == JsonArrayConst(_rhs))
|
if (JsonArrayConst(&lhs) == JsonArrayConst(rhs_))
|
||||||
return COMPARE_RESULT_EQUAL;
|
return COMPARE_RESULT_EQUAL;
|
||||||
else
|
else
|
||||||
return COMPARE_RESULT_DIFFER;
|
return COMPARE_RESULT_DIFFER;
|
||||||
@@ -99,14 +94,12 @@ struct ArrayComparer : ComparerBase {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ObjectComparer : ComparerBase {
|
struct ObjectComparer : ComparerBase {
|
||||||
const CollectionData * _rhs;
|
const CollectionData* rhs_;
|
||||||
|
|
||||||
explicit ObjectComparer(const CollectionData & rhs)
|
explicit ObjectComparer(const CollectionData& rhs) : rhs_(&rhs) {}
|
||||||
: _rhs(&rhs) {
|
|
||||||
}
|
|
||||||
|
|
||||||
CompareResult visitObject(const CollectionData & lhs) {
|
CompareResult visitObject(const CollectionData& lhs) {
|
||||||
if (JsonObjectConst(&lhs) == JsonObjectConst(_rhs))
|
if (JsonObjectConst(&lhs) == JsonObjectConst(rhs_))
|
||||||
return COMPARE_RESULT_EQUAL;
|
return COMPARE_RESULT_EQUAL;
|
||||||
else
|
else
|
||||||
return COMPARE_RESULT_DIFFER;
|
return COMPARE_RESULT_DIFFER;
|
||||||
@@ -114,17 +107,15 @@ struct ObjectComparer : ComparerBase {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct RawComparer : ComparerBase {
|
struct RawComparer : ComparerBase {
|
||||||
const char * _rhsData;
|
const char* rhsData_;
|
||||||
size_t _rhsSize;
|
size_t rhsSize_;
|
||||||
|
|
||||||
explicit RawComparer(const char * rhsData, size_t rhsSize)
|
explicit RawComparer(const char* rhsData, size_t rhsSize)
|
||||||
: _rhsData(rhsData)
|
: rhsData_(rhsData), rhsSize_(rhsSize) {}
|
||||||
, _rhsSize(rhsSize) {
|
|
||||||
}
|
|
||||||
|
|
||||||
CompareResult visitRawJson(const char * lhsData, size_t lhsSize) {
|
CompareResult visitRawJson(const char* lhsData, size_t lhsSize) {
|
||||||
size_t size = _rhsSize < lhsSize ? _rhsSize : lhsSize;
|
size_t size = rhsSize_ < lhsSize ? rhsSize_ : lhsSize;
|
||||||
int n = memcmp(lhsData, _rhsData, size);
|
int n = memcmp(lhsData, rhsData_, size);
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
return COMPARE_RESULT_LESS;
|
return COMPARE_RESULT_LESS;
|
||||||
else if (n > 0)
|
else if (n > 0)
|
||||||
@@ -135,18 +126,16 @@ struct RawComparer : ComparerBase {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct VariantComparer : ComparerBase {
|
struct VariantComparer : ComparerBase {
|
||||||
const VariantData * rhs;
|
const VariantData* rhs;
|
||||||
|
|
||||||
explicit VariantComparer(const VariantData * value)
|
explicit VariantComparer(const VariantData* value) : rhs(value) {}
|
||||||
: rhs(value) {
|
|
||||||
}
|
|
||||||
|
|
||||||
CompareResult visitArray(const CollectionData & lhs) {
|
CompareResult visitArray(const CollectionData& lhs) {
|
||||||
ArrayComparer comparer(lhs);
|
ArrayComparer comparer(lhs);
|
||||||
return accept(comparer);
|
return accept(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompareResult visitObject(const CollectionData & lhs) {
|
CompareResult visitObject(const CollectionData& lhs) {
|
||||||
ObjectComparer comparer(lhs);
|
ObjectComparer comparer(lhs);
|
||||||
return accept(comparer);
|
return accept(comparer);
|
||||||
}
|
}
|
||||||
@@ -156,12 +145,12 @@ struct VariantComparer : ComparerBase {
|
|||||||
return accept(comparer);
|
return accept(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompareResult visitString(const char * lhs, size_t) {
|
CompareResult visitString(const char* lhs, size_t) {
|
||||||
Comparer<const char *> comparer(lhs);
|
Comparer<const char*> comparer(lhs);
|
||||||
return accept(comparer);
|
return accept(comparer);
|
||||||
}
|
}
|
||||||
|
|
||||||
CompareResult visitRawJson(const char * lhsData, size_t lhsSize) {
|
CompareResult visitRawJson(const char* lhsData, size_t lhsSize) {
|
||||||
RawComparer comparer(lhsData, lhsSize);
|
RawComparer comparer(lhsData, lhsSize);
|
||||||
return accept(comparer);
|
return accept(comparer);
|
||||||
}
|
}
|
||||||
@@ -188,7 +177,7 @@ struct VariantComparer : ComparerBase {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename TComparer>
|
template <typename TComparer>
|
||||||
CompareResult accept(TComparer & comparer) {
|
CompareResult accept(TComparer& comparer) {
|
||||||
CompareResult reversedResult = variantAccept(rhs, comparer);
|
CompareResult reversedResult = variantAccept(rhs, comparer);
|
||||||
switch (reversedResult) {
|
switch (reversedResult) {
|
||||||
case COMPARE_RESULT_GREATER:
|
case COMPARE_RESULT_GREATER:
|
||||||
@@ -202,14 +191,15 @@ struct VariantComparer : ComparerBase {
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct Comparer<T, typename enable_if<is_convertible<T, ArduinoJson::JsonVariantConst>::value>::type> : VariantComparer {
|
struct Comparer<T, typename enable_if<is_convertible<
|
||||||
explicit Comparer(const T & value)
|
T, ArduinoJson::JsonVariantConst>::value>::type>
|
||||||
: VariantComparer(VariantAttorney::getData(value)) {
|
: VariantComparer {
|
||||||
}
|
explicit Comparer(const T& value)
|
||||||
|
: VariantComparer(VariantAttorney::getData(value)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
CompareResult compare(ArduinoJson::JsonVariantConst lhs, const T & rhs) {
|
CompareResult compare(ArduinoJson::JsonVariantConst lhs, const T& rhs) {
|
||||||
Comparer<T> comparer(rhs);
|
Comparer<T> comparer(rhs);
|
||||||
return variantAccept(VariantAttorney::getData(lhs), comparer);
|
return variantAccept(VariantAttorney::getData(lhs), comparer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,67 +11,50 @@
|
|||||||
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
#include <ArduinoJson/Strings/StringAdapters.hpp>
|
||||||
#include <ArduinoJson/Variant/VariantContent.hpp>
|
#include <ArduinoJson/Variant/VariantContent.hpp>
|
||||||
|
|
||||||
// VariantData can't have a constructor (to be a POD), so we have no way to fix
|
|
||||||
// this warning
|
|
||||||
#if defined(__GNUC__)
|
|
||||||
# if __GNUC__ >= 7
|
|
||||||
# pragma GCC diagnostic push
|
|
||||||
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
|
||||||
# pragma GCC diagnostic ignored "-Wuninitialized"
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
ARDUINOJSON_BEGIN_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
class VariantData {
|
class VariantData {
|
||||||
VariantContent _content; // must be first to allow cast from array to variant
|
VariantContent content_; // must be first to allow cast from array to variant
|
||||||
uint8_t _flags;
|
uint8_t flags_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Must be a POD!
|
VariantData() : flags_(VALUE_IS_NULL) {}
|
||||||
// - no constructor
|
|
||||||
// - no destructor
|
|
||||||
// - no virtual
|
|
||||||
// - no inheritance
|
|
||||||
void init() {
|
|
||||||
_flags = VALUE_IS_NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void operator=(const VariantData& src) {
|
void operator=(const VariantData& src) {
|
||||||
_content = src._content;
|
content_ = src.content_;
|
||||||
_flags = uint8_t((_flags & OWNED_KEY_BIT) | (src._flags & ~OWNED_KEY_BIT));
|
flags_ = uint8_t((flags_ & OWNED_KEY_BIT) | (src.flags_ & ~OWNED_KEY_BIT));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TVisitor>
|
template <typename TVisitor>
|
||||||
typename TVisitor::result_type accept(TVisitor& visitor) const {
|
typename TVisitor::result_type accept(TVisitor& visitor) const {
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
case VALUE_IS_FLOAT:
|
case VALUE_IS_FLOAT:
|
||||||
return visitor.visitFloat(_content.asFloat);
|
return visitor.visitFloat(content_.asFloat);
|
||||||
|
|
||||||
case VALUE_IS_ARRAY:
|
case VALUE_IS_ARRAY:
|
||||||
return visitor.visitArray(_content.asCollection);
|
return visitor.visitArray(content_.asCollection);
|
||||||
|
|
||||||
case VALUE_IS_OBJECT:
|
case VALUE_IS_OBJECT:
|
||||||
return visitor.visitObject(_content.asCollection);
|
return visitor.visitObject(content_.asCollection);
|
||||||
|
|
||||||
case VALUE_IS_LINKED_STRING:
|
case VALUE_IS_LINKED_STRING:
|
||||||
case VALUE_IS_OWNED_STRING:
|
case VALUE_IS_OWNED_STRING:
|
||||||
return visitor.visitString(_content.asString.data,
|
return visitor.visitString(content_.asString.data,
|
||||||
_content.asString.size);
|
content_.asString.size);
|
||||||
|
|
||||||
case VALUE_IS_OWNED_RAW:
|
case VALUE_IS_OWNED_RAW:
|
||||||
case VALUE_IS_LINKED_RAW:
|
case VALUE_IS_LINKED_RAW:
|
||||||
return visitor.visitRawJson(_content.asString.data,
|
return visitor.visitRawJson(content_.asString.data,
|
||||||
_content.asString.size);
|
content_.asString.size);
|
||||||
|
|
||||||
case VALUE_IS_SIGNED_INTEGER:
|
case VALUE_IS_SIGNED_INTEGER:
|
||||||
return visitor.visitSignedInteger(_content.asSignedInteger);
|
return visitor.visitSignedInteger(content_.asSignedInteger);
|
||||||
|
|
||||||
case VALUE_IS_UNSIGNED_INTEGER:
|
case VALUE_IS_UNSIGNED_INTEGER:
|
||||||
return visitor.visitUnsignedInteger(_content.asUnsignedInteger);
|
return visitor.visitUnsignedInteger(content_.asUnsignedInteger);
|
||||||
|
|
||||||
case VALUE_IS_BOOLEAN:
|
case VALUE_IS_BOOLEAN:
|
||||||
return visitor.visitBoolean(_content.asBoolean != 0);
|
return visitor.visitBoolean(content_.asBoolean != 0);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return visitor.visitNull();
|
return visitor.visitNull();
|
||||||
@@ -89,7 +72,7 @@ class VariantData {
|
|||||||
bool asBoolean() const;
|
bool asBoolean() const;
|
||||||
|
|
||||||
CollectionData* asArray() {
|
CollectionData* asArray() {
|
||||||
return isArray() ? &_content.asCollection : 0;
|
return isArray() ? &content_.asCollection : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CollectionData* asArray() const {
|
const CollectionData* asArray() const {
|
||||||
@@ -97,11 +80,11 @@ class VariantData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const CollectionData* asCollection() const {
|
const CollectionData* asCollection() const {
|
||||||
return isCollection() ? &_content.asCollection : 0;
|
return isCollection() ? &content_.asCollection : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CollectionData* asObject() {
|
CollectionData* asObject() {
|
||||||
return isObject() ? &_content.asCollection : 0;
|
return isObject() ? &content_.asCollection : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CollectionData* asObject() const {
|
const CollectionData* asObject() const {
|
||||||
@@ -111,7 +94,7 @@ class VariantData {
|
|||||||
bool copyFrom(const VariantData& src, MemoryPool* pool);
|
bool copyFrom(const VariantData& src, MemoryPool* pool);
|
||||||
|
|
||||||
bool isArray() const {
|
bool isArray() const {
|
||||||
return (_flags & VALUE_IS_ARRAY) != 0;
|
return (flags_ & VALUE_IS_ARRAY) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isBoolean() const {
|
bool isBoolean() const {
|
||||||
@@ -119,17 +102,17 @@ class VariantData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isCollection() const {
|
bool isCollection() const {
|
||||||
return (_flags & COLLECTION_MASK) != 0;
|
return (flags_ & COLLECTION_MASK) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool isInteger() const {
|
bool isInteger() const {
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
case VALUE_IS_UNSIGNED_INTEGER:
|
case VALUE_IS_UNSIGNED_INTEGER:
|
||||||
return canConvertNumber<T>(_content.asUnsignedInteger);
|
return canConvertNumber<T>(content_.asUnsignedInteger);
|
||||||
|
|
||||||
case VALUE_IS_SIGNED_INTEGER:
|
case VALUE_IS_SIGNED_INTEGER:
|
||||||
return canConvertNumber<T>(_content.asSignedInteger);
|
return canConvertNumber<T>(content_.asSignedInteger);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -137,7 +120,7 @@ class VariantData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isFloat() const {
|
bool isFloat() const {
|
||||||
return (_flags & NUMBER_BIT) != 0;
|
return (flags_ & NUMBER_BIT) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isString() const {
|
bool isString() const {
|
||||||
@@ -145,7 +128,7 @@ class VariantData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isObject() const {
|
bool isObject() const {
|
||||||
return (_flags & VALUE_IS_OBJECT) != 0;
|
return (flags_ & VALUE_IS_OBJECT) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNull() const {
|
bool isNull() const {
|
||||||
@@ -158,30 +141,30 @@ class VariantData {
|
|||||||
|
|
||||||
void remove(size_t index) {
|
void remove(size_t index) {
|
||||||
if (isArray())
|
if (isArray())
|
||||||
_content.asCollection.removeElement(index);
|
content_.asCollection.removeElement(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
void remove(TAdaptedString key) {
|
void remove(TAdaptedString key) {
|
||||||
if (isObject())
|
if (isObject())
|
||||||
_content.asCollection.removeMember(key);
|
content_.asCollection.removeMember(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setBoolean(bool value) {
|
void setBoolean(bool value) {
|
||||||
setType(VALUE_IS_BOOLEAN);
|
setType(VALUE_IS_BOOLEAN);
|
||||||
_content.asBoolean = value;
|
content_.asBoolean = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setFloat(JsonFloat value) {
|
void setFloat(JsonFloat value) {
|
||||||
setType(VALUE_IS_FLOAT);
|
setType(VALUE_IS_FLOAT);
|
||||||
_content.asFloat = value;
|
content_.asFloat = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setLinkedRaw(SerializedValue<const char*> value) {
|
void setLinkedRaw(SerializedValue<const char*> value) {
|
||||||
if (value.data()) {
|
if (value.data()) {
|
||||||
setType(VALUE_IS_LINKED_RAW);
|
setType(VALUE_IS_LINKED_RAW);
|
||||||
_content.asString.data = value.data();
|
content_.asString.data = value.data();
|
||||||
_content.asString.size = value.size();
|
content_.asString.size = value.size();
|
||||||
} else {
|
} else {
|
||||||
setType(VALUE_IS_NULL);
|
setType(VALUE_IS_NULL);
|
||||||
}
|
}
|
||||||
@@ -192,8 +175,8 @@ class VariantData {
|
|||||||
const char* dup = pool->saveString(adaptString(value.data(), value.size()));
|
const char* dup = pool->saveString(adaptString(value.data(), value.size()));
|
||||||
if (dup) {
|
if (dup) {
|
||||||
setType(VALUE_IS_OWNED_RAW);
|
setType(VALUE_IS_OWNED_RAW);
|
||||||
_content.asString.data = dup;
|
content_.asString.data = dup;
|
||||||
_content.asString.size = value.size();
|
content_.asString.size = value.size();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
setType(VALUE_IS_NULL);
|
setType(VALUE_IS_NULL);
|
||||||
@@ -204,13 +187,13 @@ class VariantData {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
typename enable_if<is_unsigned<T>::value>::type setInteger(T value) {
|
typename enable_if<is_unsigned<T>::value>::type setInteger(T value) {
|
||||||
setType(VALUE_IS_UNSIGNED_INTEGER);
|
setType(VALUE_IS_UNSIGNED_INTEGER);
|
||||||
_content.asUnsignedInteger = static_cast<JsonUInt>(value);
|
content_.asUnsignedInteger = static_cast<JsonUInt>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
typename enable_if<is_signed<T>::value>::type setInteger(T value) {
|
typename enable_if<is_signed<T>::value>::type setInteger(T value) {
|
||||||
setType(VALUE_IS_SIGNED_INTEGER);
|
setType(VALUE_IS_SIGNED_INTEGER);
|
||||||
_content.asSignedInteger = value;
|
content_.asSignedInteger = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNull() {
|
void setNull() {
|
||||||
@@ -223,20 +206,20 @@ class VariantData {
|
|||||||
setType(VALUE_IS_LINKED_STRING);
|
setType(VALUE_IS_LINKED_STRING);
|
||||||
else
|
else
|
||||||
setType(VALUE_IS_OWNED_STRING);
|
setType(VALUE_IS_OWNED_STRING);
|
||||||
_content.asString.data = s.c_str();
|
content_.asString.data = s.c_str();
|
||||||
_content.asString.size = s.size();
|
content_.asString.size = s.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
CollectionData& toArray() {
|
CollectionData& toArray() {
|
||||||
setType(VALUE_IS_ARRAY);
|
setType(VALUE_IS_ARRAY);
|
||||||
_content.asCollection.clear();
|
content_.asCollection.clear();
|
||||||
return _content.asCollection;
|
return content_.asCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
CollectionData& toObject() {
|
CollectionData& toObject() {
|
||||||
setType(VALUE_IS_OBJECT);
|
setType(VALUE_IS_OBJECT);
|
||||||
_content.asCollection.clear();
|
content_.asCollection.clear();
|
||||||
return _content.asCollection;
|
return content_.asCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t memoryUsage() const {
|
size_t memoryUsage() const {
|
||||||
@@ -245,17 +228,17 @@ class VariantData {
|
|||||||
case VALUE_IS_OWNED_RAW:
|
case VALUE_IS_OWNED_RAW:
|
||||||
// We always add a zero at the end: the deduplication function uses it
|
// We always add a zero at the end: the deduplication function uses it
|
||||||
// to detect the beginning of the next string.
|
// to detect the beginning of the next string.
|
||||||
return _content.asString.size + 1;
|
return content_.asString.size + 1;
|
||||||
case VALUE_IS_OBJECT:
|
case VALUE_IS_OBJECT:
|
||||||
case VALUE_IS_ARRAY:
|
case VALUE_IS_ARRAY:
|
||||||
return _content.asCollection.memoryUsage();
|
return content_.asCollection.memoryUsage();
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return isCollection() ? _content.asCollection.size() : 0;
|
return isCollection() ? content_.asCollection.size() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
VariantData* addElement(MemoryPool* pool) {
|
VariantData* addElement(MemoryPool* pool) {
|
||||||
@@ -263,7 +246,7 @@ class VariantData {
|
|||||||
toArray();
|
toArray();
|
||||||
if (!isArray())
|
if (!isArray())
|
||||||
return 0;
|
return 0;
|
||||||
return _content.asCollection.addElement(pool);
|
return content_.asCollection.addElement(pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
VariantData* getElement(size_t index) const {
|
VariantData* getElement(size_t index) const {
|
||||||
@@ -276,7 +259,7 @@ class VariantData {
|
|||||||
toArray();
|
toArray();
|
||||||
if (!isArray())
|
if (!isArray())
|
||||||
return 0;
|
return 0;
|
||||||
return _content.asCollection.getOrAddElement(index, pool);
|
return content_.asCollection.getOrAddElement(index, pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
@@ -291,18 +274,18 @@ class VariantData {
|
|||||||
toObject();
|
toObject();
|
||||||
if (!isObject())
|
if (!isObject())
|
||||||
return 0;
|
return 0;
|
||||||
return _content.asCollection.getOrAddMember(key, pool);
|
return content_.asCollection.getOrAddMember(key, pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) {
|
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) {
|
||||||
if (_flags & OWNED_VALUE_BIT)
|
if (flags_ & OWNED_VALUE_BIT)
|
||||||
_content.asString.data += stringDistance;
|
content_.asString.data += stringDistance;
|
||||||
if (_flags & COLLECTION_MASK)
|
if (flags_ & COLLECTION_MASK)
|
||||||
_content.asCollection.movePointers(stringDistance, variantDistance);
|
content_.asCollection.movePointers(stringDistance, variantDistance);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t type() const {
|
uint8_t type() const {
|
||||||
return _flags & VALUE_MASK;
|
return flags_ & VALUE_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename TAdaptedString>
|
template <typename TAdaptedString>
|
||||||
@@ -317,29 +300,23 @@ class VariantData {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void setType(uint8_t t) {
|
void setType(uint8_t t) {
|
||||||
_flags &= OWNED_KEY_BIT;
|
flags_ &= OWNED_KEY_BIT;
|
||||||
_flags |= t;
|
flags_ |= t;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VariantStringSetter {
|
struct VariantStringSetter {
|
||||||
VariantStringSetter(VariantData* instance) : _instance(instance) {}
|
VariantStringSetter(VariantData* instance) : instance_(instance) {}
|
||||||
|
|
||||||
template <typename TStoredString>
|
template <typename TStoredString>
|
||||||
void operator()(TStoredString s) {
|
void operator()(TStoredString s) {
|
||||||
if (s)
|
if (s)
|
||||||
_instance->setString(s);
|
instance_->setString(s);
|
||||||
else
|
else
|
||||||
_instance->setNull();
|
instance_->setNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
VariantData* _instance;
|
VariantData* instance_;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
ARDUINOJSON_END_PRIVATE_NAMESPACE
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
|
||||||
# if __GNUC__ >= 8
|
|
||||||
# pragma GCC diagnostic pop
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -19,16 +19,16 @@ template <typename T>
|
|||||||
inline T VariantData::asIntegral() const {
|
inline T VariantData::asIntegral() const {
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
case VALUE_IS_BOOLEAN:
|
case VALUE_IS_BOOLEAN:
|
||||||
return _content.asBoolean;
|
return content_.asBoolean;
|
||||||
case VALUE_IS_UNSIGNED_INTEGER:
|
case VALUE_IS_UNSIGNED_INTEGER:
|
||||||
return convertNumber<T>(_content.asUnsignedInteger);
|
return convertNumber<T>(content_.asUnsignedInteger);
|
||||||
case VALUE_IS_SIGNED_INTEGER:
|
case VALUE_IS_SIGNED_INTEGER:
|
||||||
return convertNumber<T>(_content.asSignedInteger);
|
return convertNumber<T>(content_.asSignedInteger);
|
||||||
case VALUE_IS_LINKED_STRING:
|
case VALUE_IS_LINKED_STRING:
|
||||||
case VALUE_IS_OWNED_STRING:
|
case VALUE_IS_OWNED_STRING:
|
||||||
return parseNumber<T>(_content.asString.data);
|
return parseNumber<T>(content_.asString.data);
|
||||||
case VALUE_IS_FLOAT:
|
case VALUE_IS_FLOAT:
|
||||||
return convertNumber<T>(_content.asFloat);
|
return convertNumber<T>(content_.asFloat);
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -37,12 +37,12 @@ inline T VariantData::asIntegral() const {
|
|||||||
inline bool VariantData::asBoolean() const {
|
inline bool VariantData::asBoolean() const {
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
case VALUE_IS_BOOLEAN:
|
case VALUE_IS_BOOLEAN:
|
||||||
return _content.asBoolean;
|
return content_.asBoolean;
|
||||||
case VALUE_IS_SIGNED_INTEGER:
|
case VALUE_IS_SIGNED_INTEGER:
|
||||||
case VALUE_IS_UNSIGNED_INTEGER:
|
case VALUE_IS_UNSIGNED_INTEGER:
|
||||||
return _content.asUnsignedInteger != 0;
|
return content_.asUnsignedInteger != 0;
|
||||||
case VALUE_IS_FLOAT:
|
case VALUE_IS_FLOAT:
|
||||||
return _content.asFloat != 0;
|
return content_.asFloat != 0;
|
||||||
case VALUE_IS_NULL:
|
case VALUE_IS_NULL:
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
@@ -55,16 +55,16 @@ template <typename T>
|
|||||||
inline T VariantData::asFloat() const {
|
inline T VariantData::asFloat() const {
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
case VALUE_IS_BOOLEAN:
|
case VALUE_IS_BOOLEAN:
|
||||||
return static_cast<T>(_content.asBoolean);
|
return static_cast<T>(content_.asBoolean);
|
||||||
case VALUE_IS_UNSIGNED_INTEGER:
|
case VALUE_IS_UNSIGNED_INTEGER:
|
||||||
return static_cast<T>(_content.asUnsignedInteger);
|
return static_cast<T>(content_.asUnsignedInteger);
|
||||||
case VALUE_IS_SIGNED_INTEGER:
|
case VALUE_IS_SIGNED_INTEGER:
|
||||||
return static_cast<T>(_content.asSignedInteger);
|
return static_cast<T>(content_.asSignedInteger);
|
||||||
case VALUE_IS_LINKED_STRING:
|
case VALUE_IS_LINKED_STRING:
|
||||||
case VALUE_IS_OWNED_STRING:
|
case VALUE_IS_OWNED_STRING:
|
||||||
return parseNumber<T>(_content.asString.data);
|
return parseNumber<T>(content_.asString.data);
|
||||||
case VALUE_IS_FLOAT:
|
case VALUE_IS_FLOAT:
|
||||||
return static_cast<T>(_content.asFloat);
|
return static_cast<T>(content_.asFloat);
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -73,10 +73,10 @@ inline T VariantData::asFloat() const {
|
|||||||
inline JsonString VariantData::asString() const {
|
inline JsonString VariantData::asString() const {
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
case VALUE_IS_LINKED_STRING:
|
case VALUE_IS_LINKED_STRING:
|
||||||
return JsonString(_content.asString.data, _content.asString.size,
|
return JsonString(content_.asString.data, content_.asString.size,
|
||||||
JsonString::Linked);
|
JsonString::Linked);
|
||||||
case VALUE_IS_OWNED_STRING:
|
case VALUE_IS_OWNED_STRING:
|
||||||
return JsonString(_content.asString.data, _content.asString.size,
|
return JsonString(content_.asString.data, content_.asString.size,
|
||||||
JsonString::Copied);
|
JsonString::Copied);
|
||||||
default:
|
default:
|
||||||
return JsonString();
|
return JsonString();
|
||||||
@@ -86,20 +86,20 @@ inline JsonString VariantData::asString() const {
|
|||||||
inline bool VariantData::copyFrom(const VariantData& src, MemoryPool* pool) {
|
inline bool VariantData::copyFrom(const VariantData& src, MemoryPool* pool) {
|
||||||
switch (src.type()) {
|
switch (src.type()) {
|
||||||
case VALUE_IS_ARRAY:
|
case VALUE_IS_ARRAY:
|
||||||
return toArray().copyFrom(src._content.asCollection, pool);
|
return toArray().copyFrom(src.content_.asCollection, pool);
|
||||||
case VALUE_IS_OBJECT:
|
case VALUE_IS_OBJECT:
|
||||||
return toObject().copyFrom(src._content.asCollection, pool);
|
return toObject().copyFrom(src.content_.asCollection, pool);
|
||||||
case VALUE_IS_OWNED_STRING: {
|
case VALUE_IS_OWNED_STRING: {
|
||||||
JsonString value = src.asString();
|
JsonString value = src.asString();
|
||||||
return setString(adaptString(value), pool);
|
return setString(adaptString(value), pool);
|
||||||
}
|
}
|
||||||
case VALUE_IS_OWNED_RAW:
|
case VALUE_IS_OWNED_RAW:
|
||||||
return storeOwnedRaw(
|
return storeOwnedRaw(
|
||||||
serialized(src._content.asString.data, src._content.asString.size),
|
serialized(src.content_.asString.data, src.content_.asString.size),
|
||||||
pool);
|
pool);
|
||||||
default:
|
default:
|
||||||
setType(src.type());
|
setType(src.type());
|
||||||
_content = src._content;
|
content_ = src.content_;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ class VariantSlot {
|
|||||||
// CAUTION: same layout as VariantData
|
// CAUTION: same layout as VariantData
|
||||||
// we cannot use composition because it adds padding
|
// we cannot use composition because it adds padding
|
||||||
// (+20% on ESP8266 for example)
|
// (+20% on ESP8266 for example)
|
||||||
VariantContent _content;
|
VariantContent content_;
|
||||||
uint8_t _flags;
|
uint8_t flags_;
|
||||||
VariantSlotDiff _next;
|
VariantSlotDiff next_;
|
||||||
const char* _key;
|
const char* key_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Must be a POD!
|
// Must be a POD!
|
||||||
@@ -30,15 +30,15 @@ class VariantSlot {
|
|||||||
// - no inheritance
|
// - no inheritance
|
||||||
|
|
||||||
VariantData* data() {
|
VariantData* data() {
|
||||||
return reinterpret_cast<VariantData*>(&_content);
|
return reinterpret_cast<VariantData*>(&content_);
|
||||||
}
|
}
|
||||||
|
|
||||||
const VariantData* data() const {
|
const VariantData* data() const {
|
||||||
return reinterpret_cast<const VariantData*>(&_content);
|
return reinterpret_cast<const VariantData*>(&content_);
|
||||||
}
|
}
|
||||||
|
|
||||||
VariantSlot* next() {
|
VariantSlot* next() {
|
||||||
return _next ? this + _next : 0;
|
return next_ ? this + next_ : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const VariantSlot* next() const {
|
const VariantSlot* next() const {
|
||||||
@@ -48,9 +48,9 @@ class VariantSlot {
|
|||||||
VariantSlot* next(size_t distance) {
|
VariantSlot* next(size_t distance) {
|
||||||
VariantSlot* slot = this;
|
VariantSlot* slot = this;
|
||||||
while (distance--) {
|
while (distance--) {
|
||||||
if (!slot->_next)
|
if (!slot->next_)
|
||||||
return 0;
|
return 0;
|
||||||
slot += slot->_next;
|
slot += slot->next_;
|
||||||
}
|
}
|
||||||
return slot;
|
return slot;
|
||||||
}
|
}
|
||||||
@@ -64,7 +64,7 @@ class VariantSlot {
|
|||||||
numeric_limits<VariantSlotDiff>::lowest());
|
numeric_limits<VariantSlotDiff>::lowest());
|
||||||
ARDUINOJSON_ASSERT(!slot || slot - this <=
|
ARDUINOJSON_ASSERT(!slot || slot - this <=
|
||||||
numeric_limits<VariantSlotDiff>::highest());
|
numeric_limits<VariantSlotDiff>::highest());
|
||||||
_next = VariantSlotDiff(slot ? slot - this : 0);
|
next_ = VariantSlotDiff(slot ? slot - this : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNextNotNull(VariantSlot* slot) {
|
void setNextNotNull(VariantSlot* slot) {
|
||||||
@@ -73,39 +73,39 @@ class VariantSlot {
|
|||||||
numeric_limits<VariantSlotDiff>::lowest());
|
numeric_limits<VariantSlotDiff>::lowest());
|
||||||
ARDUINOJSON_ASSERT(slot - this <=
|
ARDUINOJSON_ASSERT(slot - this <=
|
||||||
numeric_limits<VariantSlotDiff>::highest());
|
numeric_limits<VariantSlotDiff>::highest());
|
||||||
_next = VariantSlotDiff(slot - this);
|
next_ = VariantSlotDiff(slot - this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setKey(JsonString k) {
|
void setKey(JsonString k) {
|
||||||
ARDUINOJSON_ASSERT(k);
|
ARDUINOJSON_ASSERT(k);
|
||||||
if (k.isLinked())
|
if (k.isLinked())
|
||||||
_flags &= VALUE_MASK;
|
flags_ &= VALUE_MASK;
|
||||||
else
|
else
|
||||||
_flags |= OWNED_KEY_BIT;
|
flags_ |= OWNED_KEY_BIT;
|
||||||
_key = k.c_str();
|
key_ = k.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* key() const {
|
const char* key() const {
|
||||||
return _key;
|
return key_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ownsKey() const {
|
bool ownsKey() const {
|
||||||
return (_flags & OWNED_KEY_BIT) != 0;
|
return (flags_ & OWNED_KEY_BIT) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
_next = 0;
|
next_ = 0;
|
||||||
_flags = 0;
|
flags_ = 0;
|
||||||
_key = 0;
|
key_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) {
|
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) {
|
||||||
if (_flags & OWNED_KEY_BIT)
|
if (flags_ & OWNED_KEY_BIT)
|
||||||
_key += stringDistance;
|
key_ += stringDistance;
|
||||||
if (_flags & OWNED_VALUE_BIT)
|
if (flags_ & OWNED_VALUE_BIT)
|
||||||
_content.asString.data += stringDistance;
|
content_.asString.data += stringDistance;
|
||||||
if (_flags & COLLECTION_MASK)
|
if (flags_ & COLLECTION_MASK)
|
||||||
_content.asCollection.movePointers(stringDistance, variantDistance);
|
content_.asCollection.movePointers(stringDistance, variantDistance);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define ARDUINOJSON_VERSION "6.21.0"
|
#define ARDUINOJSON_VERSION "6.21.2"
|
||||||
#define ARDUINOJSON_VERSION_MAJOR 6
|
#define ARDUINOJSON_VERSION_MAJOR 6
|
||||||
#define ARDUINOJSON_VERSION_MINOR 21
|
#define ARDUINOJSON_VERSION_MINOR 21
|
||||||
#define ARDUINOJSON_VERSION_REVISION 0
|
#define ARDUINOJSON_VERSION_REVISION 2
|
||||||
|
|||||||
91
lib/ArduinoJson/src/CMakeLists.txt
Normal file
91
lib/ArduinoJson/src/CMakeLists.txt
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
# ArduinoJson - https://arduinojson.org
|
||||||
|
# Copyright © 2014-2023, Benoit BLANCHON
|
||||||
|
# MIT License
|
||||||
|
|
||||||
|
# I have no idea what this is about, I simply followed the instructions from:
|
||||||
|
# https://dominikberner.ch/cmake-interface-lib/
|
||||||
|
|
||||||
|
add_library(ArduinoJson INTERFACE)
|
||||||
|
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
# Adding the install interface generator expression makes sure that the include
|
||||||
|
# files are installed to the proper location (provided by GNUInstallDirs)
|
||||||
|
target_include_directories(ArduinoJson
|
||||||
|
INTERFACE
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||||
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(ArduinoJson
|
||||||
|
INTERFACE
|
||||||
|
ARDUINOJSON_DEBUG=$<CONFIG:Debug>
|
||||||
|
)
|
||||||
|
|
||||||
|
# locations are provided by GNUInstallDirs
|
||||||
|
install(
|
||||||
|
TARGETS
|
||||||
|
ArduinoJson
|
||||||
|
EXPORT
|
||||||
|
ArduinoJson_Targets
|
||||||
|
ARCHIVE DESTINATION
|
||||||
|
${CMAKE_INSTALL_LIBDIR}
|
||||||
|
LIBRARY DESTINATION
|
||||||
|
${CMAKE_INSTALL_LIBDIR}
|
||||||
|
RUNTIME DESTINATION
|
||||||
|
${CMAKE_INSTALL_BINDIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
include(CMakePackageConfigHelpers)
|
||||||
|
|
||||||
|
if(${CMAKE_VERSION} VERSION_GREATER "3.14.0")
|
||||||
|
set(ARCH_INDEPENDENT "ARCH_INDEPENDENT")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
write_basic_package_version_file(
|
||||||
|
"${PROJECT_BINARY_DIR}/ArduinoJsonConfigVersion.cmake"
|
||||||
|
VERSION
|
||||||
|
${PROJECT_VERSION}
|
||||||
|
COMPATIBILITY
|
||||||
|
SameMajorVersion
|
||||||
|
${ARCH_INDEPENDENT}
|
||||||
|
)
|
||||||
|
|
||||||
|
configure_package_config_file(
|
||||||
|
"${PROJECT_SOURCE_DIR}/extras/ArduinoJsonConfig.cmake.in"
|
||||||
|
"${PROJECT_BINARY_DIR}/ArduinoJsonConfig.cmake"
|
||||||
|
INSTALL_DESTINATION
|
||||||
|
${CMAKE_INSTALL_DATAROOTDIR}/ArduinoJson/cmake
|
||||||
|
)
|
||||||
|
|
||||||
|
install(
|
||||||
|
EXPORT
|
||||||
|
ArduinoJson_Targets
|
||||||
|
FILE
|
||||||
|
ArduinoJsonTargets.cmake
|
||||||
|
DESTINATION
|
||||||
|
${CMAKE_INSTALL_DATAROOTDIR}/ArduinoJson/cmake
|
||||||
|
)
|
||||||
|
|
||||||
|
install(
|
||||||
|
FILES
|
||||||
|
"${PROJECT_BINARY_DIR}/ArduinoJsonConfig.cmake"
|
||||||
|
"${PROJECT_BINARY_DIR}/ArduinoJsonConfigVersion.cmake"
|
||||||
|
DESTINATION
|
||||||
|
"${CMAKE_INSTALL_DATAROOTDIR}/ArduinoJson/cmake"
|
||||||
|
)
|
||||||
|
|
||||||
|
install(
|
||||||
|
FILES
|
||||||
|
ArduinoJson.h
|
||||||
|
ArduinoJson.hpp
|
||||||
|
DESTINATION
|
||||||
|
include
|
||||||
|
)
|
||||||
|
|
||||||
|
install(
|
||||||
|
DIRECTORY
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/ArduinoJson"
|
||||||
|
DESTINATION
|
||||||
|
include
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user