update ArduinoJson to latest v6.20.0 (saves 1600 bytes in flash. whoot!)

This commit is contained in:
Proddy
2022-12-27 21:48:03 +01:00
parent 6390f4aa48
commit 5d45064c2d
96 changed files with 3504 additions and 3314 deletions

View File

@@ -1,6 +1,41 @@
ArduinoJson: change log
=======================
v6.20.0 (2022-12-26)
-------
* Add `JsonVariant::shallowCopy()` (issue #1343)
* Fix `9.22337e+18 is outside the range of representable values of type 'long'`
* Fix comparison operators for `JsonArray`, `JsonArrayConst`, `JsonObject`, and `JsonObjectConst`
* Fix lax parsing of `true`, `false`, and `null` (issue #1781)
* Remove undocumented `accept()` functions
* Rename `addElement()` to `add()`
* Remove `getElement()`, `getOrAddElement()`, `getMember()`, and `getOrAddMember()`
* Remove undocumented `JsonDocument::data()` and `JsonDocument::memoryPool()`
* Remove undocumented `JsonArrayIterator::internal()` and `JsonObjectIterator::internal()`
* Rename things in `ARDUINOJSON_NAMESPACE` to match the public names
* Add documentation to most public symbols
* Remove support for naked `char` (was deprecated since 6.18.0)
> ### BREAKING CHANGES
>
> This release hides `JsonVariant`'s functions that were only intended for internal use.
> If you were using them in your programs, you must replace with `operator[]` and `to<JsonVariant>()`, like so:
>
> ```c++
> // before
> JsonVariant a = variant.getElement(idx);
> JsonVariant b = variant.getOrAddElement(idx);
> JsonVariant c = variant.getMember(key);
> JsonVariant d = variant.getOrAddMember(key);
>
> // after
> JsonVariant a = variant[idx];
> JsonVariant b = idx < variant.size() ? variant[idx] : variant[idx].to<JsonVariant>();
> JsonVariant c = variant[key];
> JsonVariant d = variant.containsKey(key) ? variant[key] : variant[key].to<JsonVariant>();
> ```
v6.19.4 (2022-04-05)
-------

View File

@@ -1,14 +1,15 @@
![ArduinoJson](banner.svg)
<p align="center">
<a href="https://arduinojson.org/"><img alt="ArduinoJson" src="logo.svg" /></a>
</p>
---
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/bblanchon/ArduinoJson/Continuous%20Integration?logo=github)](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A6.x)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/bblanchon/ArduinoJson/ci.yml?branch=6.x)](https://github.com/bblanchon/ArduinoJson/actions?query=workflow%3A%22Continuous+Integration%22+branch%3A6.x)
[![Continuous Integration](https://ci.appveyor.com/api/projects/status/m7s53wav1l0abssg/branch/6.x?svg=true)](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/6.x)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/arduinojson.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:arduinojson)
[![LGTM Grade](https://img.shields.io/lgtm/grade/cpp/github/bblanchon/ArduinoJson?label=quality&logo=lgtm)](https://lgtm.com/projects/g/bblanchon/ArduinoJson/)
[![Coveralls branch](https://img.shields.io/coveralls/github/bblanchon/ArduinoJson/6.x?logo=coveralls)](https://coveralls.io/github/bblanchon/ArduinoJson?branch=6.x)
[![Arduino Library Manager](https://img.shields.io/static/v1?label=Arduino&message=v6.19.4&logo=arduino&logoColor=white&color=blue)](https://www.ardu-badge.com/ArduinoJson/6.19.4)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/bblanchon/library/ArduinoJson.svg?version=6.19.4)](https://registry.platformio.org/packages/libraries/bblanchon/ArduinoJson?version=6.19.4)
[![Arduino Library Manager](https://img.shields.io/static/v1?label=Arduino&message=v6.20.0&logo=arduino&logoColor=white&color=blue)](https://www.ardu-badge.com/ArduinoJson/6.20.0)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/bblanchon/library/ArduinoJson.svg?version=6.20.0)](https://registry.platformio.org/packages/libraries/bblanchon/ArduinoJson?version=6.20.0)
[![GitHub stars](https://img.shields.io/github/stars/bblanchon/ArduinoJson?style=flat&logo=github)](https://github.com/bblanchon/ArduinoJson/stargazers)
[![GitHub Sponsors](https://img.shields.io/github/sponsors/bblanchon?logo=github)](https://github.com/sponsors/bblanchon)
@@ -16,32 +17,32 @@ ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
## Features
* [JSON deserialization](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme)
* [Optionally decodes UTF-16 escape sequences to UTF-8](https://arduinojson.org/v6/api/config/decode_unicode/?utm_source=github&utm_medium=readme)
* [Optionally stores links to the input buffer (zero-copy)](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme)
* [Optionally supports comments in the input](https://arduinojson.org/v6/api/config/enable_comments/?utm_source=github&utm_medium=readme)
* [Optionally filters the input to keep only desired values](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme#filtering)
* [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/?utm_source=github&utm_medium=readme)
* [Can write to a buffer or a stream](https://arduinojson.org/v6/api/json/serializejson/?utm_source=github&utm_medium=readme)
* [Optionally indents the document (prettified JSON)](https://arduinojson.org/v6/api/json/serializejsonpretty/?utm_source=github&utm_medium=readme)
* [MessagePack serialization](https://arduinojson.org/v6/api/msgpack/serializemsgpack/?utm_source=github&utm_medium=readme)
* [MessagePack deserialization](https://arduinojson.org/v6/api/msgpack/deserializemsgpack/?utm_source=github&utm_medium=readme)
* [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/?utm_source=github&utm_medium=readme)
* [Almost 10% faster than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/?utm_source=github&utm_medium=readme)
* [Consumes roughly 10% less RAM than the "official" Arduino_JSON library](https://arduinojson.org/2019/11/19/arduinojson-vs-arduino_json/?utm_source=github&utm_medium=readme)
* [Fixed memory allocation, no heap fragmentation](https://arduinojson.org/v6/api/jsondocument/?utm_source=github&utm_medium=readme)
* [Optionally works without heap memory (zero malloc)](https://arduinojson.org/v6/api/staticjsondocument/?utm_source=github&utm_medium=readme)
* [Deduplicates strings](https://arduinojson.org/news/2020/08/01/version-6-16-0/?utm_source=github&utm_medium=readme)
* [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/?utm_source=github&utm_medium=readme)
* Supports [`String`](https://arduinojson.org/v6/api/config/enable_arduino_string/?utm_source=github&utm_medium=readme), [`std::string`](https://arduinojson.org/v6/api/config/enable_std_string/?utm_source=github&utm_medium=readme), and [`std::string_view`](https://arduinojson.org/v6/api/config/enable_string_view/?utm_source=github&utm_medium=readme)
* Supports [`Stream`](https://arduinojson.org/v6/api/config/enable_arduino_stream/?utm_source=github&utm_medium=readme) and [`std::istream`/`std::ostream`](https://arduinojson.org/v6/api/config/enable_std_stream/?utm_source=github&utm_medium=readme)
* Supports [Flash strings](https://arduinojson.org/v6/api/config/enable_progmem/?utm_source=github&utm_medium=readme)
* Supports [custom readers](https://arduinojson.org/v6/api/json/deserializejson/?utm_source=github&utm_medium=readme#custom-reader) and [custom writers](https://arduinojson.org/v6/api/json/serializejson/?utm_source=github&utm_medium=readme#custom-writer)
* Supports [custom converters](https://arduinojson.org/news/2021/05/04/version-6-18-0/?utm_source=github&utm_medium=readme)
* 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++98, C++11, C++14 and C++17
@@ -69,15 +70,15 @@ ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
* [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/?utm_source=github&utm_medium=readme)
* [CMake friendly](https://arduinojson.org/v6/how-to/use-arduinojson-with-cmake/)
* Well designed
* [Elegant API](http://arduinojson.org/v6/example/?utm_source=github&utm_medium=readme)
* [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/?utm_source=github&utm_medium=readme)
* [`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/?utm_source=github&utm_medium=readme#integer-overflows)
* 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
@@ -87,12 +88,12 @@ ArduinoJson is a C++ JSON library for Arduino and IoT (Internet Of Things).
* [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/?utm_source=github&utm_medium=readme)
* [Examples](https://arduinojson.org/v6/example/?utm_source=github&utm_medium=readme)
* [How-tos](https://arduinojson.org/v6/example/?utm_source=github&utm_medium=readme)
* [FAQ](https://arduinojson.org/v6/faq/?utm_source=github&utm_medium=readme)
* [Troubleshooter](https://arduinojson.org/v6/troubleshooter/?utm_source=github&utm_medium=readme)
* [Book](https://arduinojson.org/book/?utm_source=github&utm_medium=readme)
* [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)
@@ -118,7 +119,7 @@ double latitude = doc["data"][0];
double longitude = doc["data"][1];
```
See the [tutorial on arduinojson.org](https://arduinojson.org/doc/decoding/?utm_source=github&utm_medium=readme)
See the [tutorial on arduinojson.org](https://arduinojson.org/v6/doc/deserialization/)
### Serialization
@@ -137,16 +138,13 @@ serializeJson(doc, Serial);
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
```
See the [tutorial on arduinojson.org](https://arduinojson.org/doc/encoding/?utm_source=github&utm_medium=readme)
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://techexplorations.com/" rel="sponsored">
<img alt="Tech Explorations" src="https://arduinojson.org/images/2021/10/techexplorations.png" width="200">
</a>
<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>

View File

@@ -21,19 +21,19 @@
# endif
#endif
#include "ArduinoJson/Array/ArrayRef.hpp"
#include "ArduinoJson/Object/ObjectRef.hpp"
#include "ArduinoJson/Variant/VariantRef.hpp"
#include "ArduinoJson/Array/JsonArray.hpp"
#include "ArduinoJson/Object/JsonObject.hpp"
#include "ArduinoJson/Variant/JsonVariantConst.hpp"
#include "ArduinoJson/Document/DynamicJsonDocument.hpp"
#include "ArduinoJson/Document/StaticJsonDocument.hpp"
#include "ArduinoJson/Array/ArrayImpl.hpp"
#include "ArduinoJson/Array/ElementProxy.hpp"
#include "ArduinoJson/Array/JsonArrayImpl.hpp"
#include "ArduinoJson/Array/Utilities.hpp"
#include "ArduinoJson/Collection/CollectionImpl.hpp"
#include "ArduinoJson/Object/JsonObjectImpl.hpp"
#include "ArduinoJson/Object/MemberProxy.hpp"
#include "ArduinoJson/Object/ObjectImpl.hpp"
#include "ArduinoJson/Variant/ConverterImpl.hpp"
#include "ArduinoJson/Variant/VariantCompare.hpp"
#include "ArduinoJson/Variant/VariantImpl.hpp"
@@ -47,25 +47,25 @@
#include "ArduinoJson/compatibility.hpp"
namespace ArduinoJson {
typedef ARDUINOJSON_NAMESPACE::ArrayConstRef JsonArrayConst;
typedef ARDUINOJSON_NAMESPACE::ArrayRef JsonArray;
typedef ARDUINOJSON_NAMESPACE::Float JsonFloat;
typedef ARDUINOJSON_NAMESPACE::Integer JsonInteger;
typedef ARDUINOJSON_NAMESPACE::ObjectConstRef JsonObjectConst;
typedef ARDUINOJSON_NAMESPACE::ObjectRef JsonObject;
typedef ARDUINOJSON_NAMESPACE::Pair JsonPair;
typedef ARDUINOJSON_NAMESPACE::PairConst JsonPairConst;
typedef ARDUINOJSON_NAMESPACE::String JsonString;
typedef ARDUINOJSON_NAMESPACE::UInt JsonUInt;
typedef ARDUINOJSON_NAMESPACE::VariantConstRef JsonVariantConst;
typedef ARDUINOJSON_NAMESPACE::VariantRef JsonVariant;
using ARDUINOJSON_NAMESPACE::BasicJsonDocument;
using ARDUINOJSON_NAMESPACE::copyArray;
using ARDUINOJSON_NAMESPACE::DeserializationError;
using ARDUINOJSON_NAMESPACE::deserializeJson;
using ARDUINOJSON_NAMESPACE::deserializeMsgPack;
using ARDUINOJSON_NAMESPACE::DynamicJsonDocument;
using ARDUINOJSON_NAMESPACE::JsonArray;
using ARDUINOJSON_NAMESPACE::JsonArrayConst;
using ARDUINOJSON_NAMESPACE::JsonDocument;
using ARDUINOJSON_NAMESPACE::JsonFloat;
using ARDUINOJSON_NAMESPACE::JsonInteger;
using ARDUINOJSON_NAMESPACE::JsonObject;
using ARDUINOJSON_NAMESPACE::JsonObjectConst;
using ARDUINOJSON_NAMESPACE::JsonPair;
using ARDUINOJSON_NAMESPACE::JsonPairConst;
using ARDUINOJSON_NAMESPACE::JsonString;
using ARDUINOJSON_NAMESPACE::JsonUInt;
using ARDUINOJSON_NAMESPACE::JsonVariant;
using ARDUINOJSON_NAMESPACE::JsonVariantConst;
using ARDUINOJSON_NAMESPACE::measureJson;
using ARDUINOJSON_NAMESPACE::serialized;
using ARDUINOJSON_NAMESPACE::serializeJson;

View File

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

View File

@@ -1,28 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Array/ArrayRef.hpp>
#include <ArduinoJson/Object/ObjectRef.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename TArray>
inline ArrayRef ArrayShortcuts<TArray>::createNestedArray() const {
return impl()->addElement().template to<ArrayRef>();
}
template <typename TArray>
inline ObjectRef ArrayShortcuts<TArray>::createNestedObject() const {
return impl()->addElement().template to<ObjectRef>();
}
template <typename TArray>
inline ElementProxy<TArray> ArrayShortcuts<TArray>::operator[](
size_t index) const {
return ElementProxy<TArray>(*impl(), index);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

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

View File

@@ -1,213 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Array/ArrayFunctions.hpp>
#include <ArduinoJson/Array/ArrayIterator.hpp>
#include <ArduinoJson/Variant/VariantData.hpp>
// Returns the size (in bytes) of an array with n elements.
// Can be very handy to determine the size of a StaticMemoryPool.
#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot))
namespace ARDUINOJSON_NAMESPACE {
class ObjectRef;
template <typename>
class ElementProxy;
template <typename TData>
class ArrayRefBase {
public:
operator VariantConstRef() const {
const void* data = _data; // prevent warning cast-align
return VariantConstRef(reinterpret_cast<const VariantData*>(data));
}
template <typename TVisitor>
FORCE_INLINE typename TVisitor::result_type accept(TVisitor& visitor) const {
return arrayAccept(_data, visitor);
}
FORCE_INLINE bool isNull() const {
return _data == 0;
}
FORCE_INLINE operator bool() const {
return _data != 0;
}
FORCE_INLINE size_t memoryUsage() const {
return _data ? _data->memoryUsage() : 0;
}
FORCE_INLINE size_t nesting() const {
return _data ? _data->nesting() : 0;
}
FORCE_INLINE size_t size() const {
return _data ? _data->size() : 0;
}
protected:
ArrayRefBase(TData* data) : _data(data) {}
TData* _data;
};
class ArrayConstRef : public ArrayRefBase<const CollectionData>,
public Visitable {
friend class ArrayRef;
typedef ArrayRefBase<const CollectionData> base_type;
public:
typedef ArrayConstRefIterator iterator;
FORCE_INLINE iterator begin() const {
if (!_data)
return iterator();
return iterator(_data->head());
}
FORCE_INLINE iterator end() const {
return iterator();
}
FORCE_INLINE ArrayConstRef() : base_type(0) {}
FORCE_INLINE ArrayConstRef(const CollectionData* data) : base_type(data) {}
FORCE_INLINE bool operator==(ArrayConstRef rhs) const {
return arrayEquals(_data, rhs._data);
}
FORCE_INLINE VariantConstRef operator[](size_t index) const {
return getElement(index);
}
FORCE_INLINE VariantConstRef getElement(size_t index) const {
return VariantConstRef(_data ? _data->getElement(index) : 0);
}
};
class ArrayRef : public ArrayRefBase<CollectionData>,
public ArrayShortcuts<ArrayRef>,
public Visitable {
typedef ArrayRefBase<CollectionData> base_type;
public:
typedef ArrayIterator iterator;
FORCE_INLINE ArrayRef() : base_type(0), _pool(0) {}
FORCE_INLINE ArrayRef(MemoryPool* pool, CollectionData* data)
: base_type(data), _pool(pool) {}
operator VariantRef() {
void* data = _data; // prevent warning cast-align
return VariantRef(_pool, reinterpret_cast<VariantData*>(data));
}
operator ArrayConstRef() const {
return ArrayConstRef(_data);
}
VariantRef addElement() const {
return VariantRef(_pool, arrayAdd(_data, _pool));
}
FORCE_INLINE iterator begin() const {
if (!_data)
return iterator();
return iterator(_pool, _data->head());
}
FORCE_INLINE iterator end() const {
return iterator();
}
// Copy a ArrayRef
FORCE_INLINE bool set(ArrayConstRef src) const {
if (!_data || !src._data)
return false;
return _data->copyFrom(*src._data, _pool);
}
FORCE_INLINE bool operator==(ArrayRef rhs) const {
return arrayEquals(_data, rhs._data);
}
// Internal use
FORCE_INLINE VariantRef getOrAddElement(size_t index) const {
return VariantRef(_pool, _data ? _data->getOrAddElement(index, _pool) : 0);
}
// Gets the value at the specified index.
FORCE_INLINE VariantRef getElement(size_t index) const {
return VariantRef(_pool, _data ? _data->getElement(index) : 0);
}
// Removes element at specified position.
FORCE_INLINE void remove(iterator it) const {
if (!_data)
return;
_data->removeSlot(it.internal());
}
// Removes element at specified index.
FORCE_INLINE void remove(size_t index) const {
if (!_data)
return;
_data->removeElement(index);
}
void clear() const {
if (!_data)
return;
_data->clear();
}
private:
MemoryPool* _pool;
};
template <>
struct Converter<ArrayConstRef> {
static void toJson(VariantConstRef src, VariantRef dst) {
variantCopyFrom(getData(dst), getData(src), getPool(dst));
}
static ArrayConstRef fromJson(VariantConstRef src) {
return ArrayConstRef(variantAsArray(getData(src)));
}
static bool checkJson(VariantConstRef src) {
const VariantData* data = getData(src);
return data && data->isArray();
}
};
template <>
struct Converter<ArrayRef> {
static void toJson(VariantConstRef src, VariantRef dst) {
variantCopyFrom(getData(dst), getData(src), getPool(dst));
}
static ArrayRef fromJson(VariantRef src) {
VariantData* data = getData(src);
MemoryPool* pool = getPool(src);
return ArrayRef(pool, data != 0 ? data->asArray() : 0);
}
static InvalidConversion<VariantConstRef, ArrayRef> fromJson(VariantConstRef);
static bool checkJson(VariantConstRef) {
return false;
}
static bool checkJson(VariantRef src) {
VariantData* data = getData(src);
return data && data->isArray();
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

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

View File

@@ -4,194 +4,57 @@
#pragma once
#include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Variant/VariantOperators.hpp>
#include <ArduinoJson/Variant/VariantShortcuts.hpp>
#include <ArduinoJson/Variant/VariantTo.hpp>
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable : 4522)
#endif
#include <ArduinoJson/Variant/VariantRefBase.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename TArray>
class ElementProxy : public VariantOperators<ElementProxy<TArray> >,
public VariantShortcuts<ElementProxy<TArray> >,
public Visitable,
public VariantTag {
typedef ElementProxy<TArray> this_type;
// A proxy class to get or set an element of an array.
// https://arduinojson.org/v6/api/jsonarray/subscript/
template <typename TUpstream>
class ElementProxy : public VariantRefBase<ElementProxy<TUpstream> >,
public VariantOperators<ElementProxy<TUpstream> > {
friend class VariantAttorney;
public:
typedef VariantRef variant_type;
ElementProxy(TUpstream upstream, size_t index)
: _upstream(upstream), _index(index) {}
FORCE_INLINE ElementProxy(TArray array, size_t index)
: _array(array), _index(index) {}
ElementProxy(const ElementProxy& src)
: _upstream(src._upstream), _index(src._index) {}
FORCE_INLINE ElementProxy(const ElementProxy& src)
: _array(src._array), _index(src._index) {}
FORCE_INLINE this_type& operator=(const this_type& src) {
getOrAddUpstreamElement().set(src.as<VariantConstRef>());
FORCE_INLINE ElementProxy& operator=(const ElementProxy& src) {
this->set(src);
return *this;
}
// Replaces the value
//
// operator=(const TValue&)
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
// std::string, String, ArrayRef, ObjectRef
template <typename T>
FORCE_INLINE this_type& operator=(const T& src) {
getOrAddUpstreamElement().set(src);
return *this;
}
//
// operator=(TValue)
// TValue = char*, const char*, const __FlashStringHelper*
template <typename T>
FORCE_INLINE this_type& operator=(T* src) {
getOrAddUpstreamElement().set(src);
FORCE_INLINE ElementProxy& operator=(const T& src) {
this->set(src);
return *this;
}
FORCE_INLINE void clear() const {
getUpstreamElement().clear();
}
FORCE_INLINE bool isNull() const {
return getUpstreamElement().isNull();
}
template <typename T>
FORCE_INLINE typename enable_if<!is_same<T, char*>::value, T>::type as()
const {
return getUpstreamElement().template as<T>();
}
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, char*>::value, const char*>::type
ARDUINOJSON_DEPRECATED("Replace as<char*>() with as<const char*>()")
as() const {
return as<const char*>();
}
template <typename T>
FORCE_INLINE operator T() const {
return getUpstreamElement();
}
template <typename T>
FORCE_INLINE bool is() const {
return getUpstreamElement().template is<T>();
}
template <typename T>
FORCE_INLINE typename VariantTo<T>::type to() const {
return getOrAddUpstreamElement().template to<T>();
}
// Replaces the value
//
// bool set(const TValue&)
// TValue = bool, long, int, short, float, double, serialized, VariantRef,
// std::string, String, ArrayRef, ObjectRef
template <typename TValue>
FORCE_INLINE bool set(const TValue& value) const {
return getOrAddUpstreamElement().set(value);
}
//
// bool set(TValue)
// TValue = char*, const char*, const __FlashStringHelper*
template <typename TValue>
FORCE_INLINE bool set(TValue* value) const {
return getOrAddUpstreamElement().set(value);
}
template <typename TVisitor>
typename TVisitor::result_type accept(TVisitor& visitor) const {
return getUpstreamElement().accept(visitor);
}
FORCE_INLINE size_t size() const {
return getUpstreamElement().size();
}
FORCE_INLINE size_t memoryUsage() const {
return getUpstreamElement().memoryUsage();
}
template <typename TNestedKey>
VariantRef getMember(TNestedKey* key) const {
return getUpstreamElement().getMember(key);
}
template <typename TNestedKey>
VariantRef getMember(const TNestedKey& key) const {
return getUpstreamElement().getMember(key);
}
template <typename TNestedKey>
VariantRef getOrAddMember(TNestedKey* key) const {
return getOrAddUpstreamElement().getOrAddMember(key);
}
template <typename TNestedKey>
VariantRef getOrAddMember(const TNestedKey& key) const {
return getOrAddUpstreamElement().getOrAddMember(key);
}
VariantRef addElement() const {
return getOrAddUpstreamElement().addElement();
}
VariantRef getElement(size_t index) const {
return getOrAddUpstreamElement().getElement(index);
}
VariantRef getOrAddElement(size_t index) const {
return getOrAddUpstreamElement().getOrAddElement(index);
}
FORCE_INLINE void remove(size_t index) const {
getUpstreamElement().remove(index);
}
// remove(char*) const
// remove(const char*) const
// remove(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove(
TChar* key) const {
getUpstreamElement().remove(key);
}
// remove(const std::string&) const
// remove(const String&) const
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
const TString& key) const {
getUpstreamElement().remove(key);
FORCE_INLINE ElementProxy& operator=(T* src) {
this->set(src);
return *this;
}
private:
FORCE_INLINE VariantRef getUpstreamElement() const {
return _array.getElement(_index);
FORCE_INLINE MemoryPool* getPool() const {
return VariantAttorney::getPool(_upstream);
}
FORCE_INLINE VariantRef getOrAddUpstreamElement() const {
return _array.getOrAddElement(_index);
FORCE_INLINE VariantData* getData() const {
return variantGetElement(VariantAttorney::getData(_upstream), _index);
}
friend void convertToJson(const this_type& src, VariantRef dst) {
dst.set(src.getUpstreamElement());
FORCE_INLINE VariantData* getOrCreateData() const {
return variantGetOrAddElement(VariantAttorney::getOrCreateData(_upstream),
_index, VariantAttorney::getPool(_upstream));
}
TArray _array;
const size_t _index;
TUpstream _upstream;
size_t _index;
};
} // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER
# pragma warning(pop)
#endif

View File

@@ -0,0 +1,210 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Array/ElementProxy.hpp>
#include <ArduinoJson/Array/JsonArrayConst.hpp>
namespace ARDUINOJSON_NAMESPACE {
class JsonObject;
// A reference to an array in a JsonDocument
// https://arduinojson.org/v6/api/jsonarray/
class JsonArray : public VariantOperators<JsonArray> {
friend class VariantAttorney;
public:
typedef JsonArrayIterator iterator;
// Constructs an unbound reference.
FORCE_INLINE JsonArray() : _data(0), _pool(0) {}
// INTERNAL USE ONLY
FORCE_INLINE JsonArray(MemoryPool* pool, CollectionData* data)
: _data(data), _pool(pool) {}
// Returns a JsonVariant pointing to the array.
// https://arduinojson.org/v6/api/jsonvariant/
operator JsonVariant() {
void* data = _data; // prevent warning cast-align
return JsonVariant(_pool, reinterpret_cast<VariantData*>(data));
}
// Returns a read-only reference to the array.
// https://arduinojson.org/v6/api/jsonarrayconst/
operator JsonArrayConst() const {
return JsonArrayConst(_data);
}
// Appends a new (null) element to the array.
// Returns a reference to the new element.
// https://arduinojson.org/v6/api/jsonarray/add/
JsonVariant add() const {
if (!_data)
return JsonVariant();
return JsonVariant(_pool, _data->addElement(_pool));
}
// Appends a value to the array.
// https://arduinojson.org/v6/api/jsonarray/add/
template <typename T>
FORCE_INLINE bool add(const T& value) const {
return add().set(value);
}
// Appends a value to the array.
// https://arduinojson.org/v6/api/jsonarray/add/
template <typename T>
FORCE_INLINE bool add(T* value) const {
return add().set(value);
}
// Returns an iterator to the first element of the array.
// https://arduinojson.org/v6/api/jsonarray/begin/
FORCE_INLINE iterator begin() const {
if (!_data)
return iterator();
return iterator(_pool, _data->head());
}
// Returns an iterator following the last element of the array.
// https://arduinojson.org/v6/api/jsonarray/end/
FORCE_INLINE iterator end() const {
return iterator();
}
// Copies an array.
// https://arduinojson.org/v6/api/jsonarray/set/
FORCE_INLINE bool set(JsonArrayConst src) const {
if (!_data || !src._data)
return false;
return _data->copyFrom(*src._data, _pool);
}
// Compares the content of two arrays.
FORCE_INLINE bool operator==(JsonArray rhs) const {
return JsonArrayConst(_data) == JsonArrayConst(rhs._data);
}
// Removes the element at the specified iterator.
// ⚠️ Doesn't release the memory associated with the removed element.
// https://arduinojson.org/v6/api/jsonarray/remove/
FORCE_INLINE void remove(iterator it) const {
if (!_data)
return;
_data->removeSlot(it._slot);
}
// Removes the element at the specified index.
// ⚠️ Doesn't release the memory associated with the removed element.
// https://arduinojson.org/v6/api/jsonarray/remove/
FORCE_INLINE void remove(size_t index) const {
if (!_data)
return;
_data->removeElement(index);
}
// Removes all the elements of the array.
// ⚠️ Doesn't release the memory associated with the removed elements.
// https://arduinojson.org/v6/api/jsonarray/clear/
void clear() const {
if (!_data)
return;
_data->clear();
}
// Gets or sets the element at the specified index.
// https://arduinojson.org/v6/api/jsonarray/subscript/
FORCE_INLINE ElementProxy<JsonArray> operator[](size_t index) const {
return ElementProxy<JsonArray>(*this, index);
}
// Creates an object and appends it to the array.
// https://arduinojson.org/v6/api/jsonarray/createnestedobject/
FORCE_INLINE JsonObject createNestedObject() const;
// Creates an array and appends it to the array.
// https://arduinojson.org/v6/api/jsonarray/createnestedarray/
FORCE_INLINE JsonArray createNestedArray() const {
return add().to<JsonArray>();
}
operator JsonVariantConst() const {
return JsonVariantConst(collectionToVariant(_data));
}
// Returns true if the reference is unbound.
// https://arduinojson.org/v6/api/jsonarray/isnull/
FORCE_INLINE bool isNull() const {
return _data == 0;
}
// Returns true if the reference is bound.
// https://arduinojson.org/v6/api/jsonarray/isnull/
FORCE_INLINE operator bool() const {
return _data != 0;
}
// Returns the number of bytes occupied by the array.
// https://arduinojson.org/v6/api/jsonarray/memoryusage/
FORCE_INLINE size_t memoryUsage() const {
return _data ? _data->memoryUsage() : 0;
}
// Returns the depth (nesting level) of the array.
// https://arduinojson.org/v6/api/jsonarray/nesting/
FORCE_INLINE size_t nesting() const {
return variantNesting(collectionToVariant(_data));
}
// Returns the number of elements in the array.
// https://arduinojson.org/v6/api/jsonarray/size/
FORCE_INLINE size_t size() const {
return _data ? _data->size() : 0;
}
private:
MemoryPool* getPool() const {
return _pool;
}
VariantData* getData() const {
return collectionToVariant(_data);
}
VariantData* getOrCreateData() const {
return collectionToVariant(_data);
}
CollectionData* _data;
MemoryPool* _pool;
};
template <>
struct Converter<JsonArray> : private VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) {
variantCopyFrom(getData(dst), getData(src), getPool(dst));
}
static JsonArray fromJson(JsonVariant src) {
VariantData* data = getData(src);
MemoryPool* pool = getPool(src);
return JsonArray(pool, data != 0 ? data->asArray() : 0);
}
static InvalidConversion<JsonVariantConst, JsonArray> fromJson(
JsonVariantConst);
static bool checkJson(JsonVariantConst) {
return false;
}
static bool checkJson(JsonVariant src) {
VariantData* data = getData(src);
return data && data->isArray();
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,134 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Array/JsonArrayIterator.hpp>
#include <ArduinoJson/Variant/VariantAttorney.hpp>
#include <ArduinoJson/Variant/VariantData.hpp>
namespace ARDUINOJSON_NAMESPACE {
class JsonObject;
// A read-only reference to an array in a JsonDocument
// https://arduinojson.org/v6/api/jsonarrayconst/
class JsonArrayConst : public VariantOperators<JsonArrayConst> {
friend class JsonArray;
friend class VariantAttorney;
public:
typedef JsonArrayConstIterator iterator;
// Returns an iterator to the first element of the array.
// https://arduinojson.org/v6/api/jsonarrayconst/begin/
FORCE_INLINE iterator begin() const {
if (!_data)
return iterator();
return iterator(_data->head());
}
// Returns an iterator to the element following the last element of the array.
// https://arduinojson.org/v6/api/jsonarrayconst/end/
FORCE_INLINE iterator end() const {
return iterator();
}
// Creates an unbound reference.
FORCE_INLINE JsonArrayConst() : _data(0) {}
// INTERNAL USE ONLY
FORCE_INLINE JsonArrayConst(const CollectionData* data) : _data(data) {}
// Compares the content of two arrays.
// Returns true if the two arrays are equal.
FORCE_INLINE bool operator==(JsonArrayConst rhs) const {
if (_data == rhs._data)
return true;
if (!_data || !rhs._data)
return false;
iterator it1 = begin();
iterator it2 = rhs.begin();
for (;;) {
bool end1 = it1 == end();
bool end2 = it2 == rhs.end();
if (end1 && end2)
return true;
if (end1 || end2)
return false;
if (*it1 != *it2)
return false;
++it1;
++it2;
}
}
// Returns the element at the specified index.
// https://arduinojson.org/v6/api/jsonarrayconst/subscript/
FORCE_INLINE JsonVariantConst operator[](size_t index) const {
return JsonVariantConst(_data ? _data->getElement(index) : 0);
}
operator JsonVariantConst() const {
return JsonVariantConst(collectionToVariant(_data));
}
// Returns true if the reference is unbound.
// https://arduinojson.org/v6/api/jsonarrayconst/isnull/
FORCE_INLINE bool isNull() const {
return _data == 0;
}
// Returns true if the reference is bound.
// https://arduinojson.org/v6/api/jsonarrayconst/isnull/
FORCE_INLINE operator bool() const {
return _data != 0;
}
// Returns the number of bytes occupied by the array.
// https://arduinojson.org/v6/api/jsonarrayconst/memoryusage/
FORCE_INLINE size_t memoryUsage() const {
return _data ? _data->memoryUsage() : 0;
}
// Returns the depth (nesting level) of the array.
// https://arduinojson.org/v6/api/jsonarrayconst/nesting/
FORCE_INLINE size_t nesting() const {
return variantNesting(collectionToVariant(_data));
}
// Returns the number of elements in the array.
// https://arduinojson.org/v6/api/jsonarrayconst/size/
FORCE_INLINE size_t size() const {
return _data ? _data->size() : 0;
}
private:
const VariantData* getData() const {
return collectionToVariant(_data);
}
const CollectionData* _data;
};
template <>
struct Converter<JsonArrayConst> : private VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) {
variantCopyFrom(getData(dst), getData(src), getPool(dst));
}
static JsonArrayConst fromJson(JsonVariantConst src) {
const VariantData* data = getData(src);
return data ? data->asArray() : 0;
}
static bool checkJson(JsonVariantConst src) {
const VariantData* data = getData(src);
return data && data->isArray();
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,32 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Array/JsonArray.hpp>
#include <ArduinoJson/Object/JsonObject.hpp>
namespace ARDUINOJSON_NAMESPACE {
inline JsonObject JsonArray::createNestedObject() const {
return add().to<JsonObject>();
}
template <typename TDerived>
inline JsonArray VariantRefBase<TDerived>::createNestedArray() const {
return add().template to<JsonArray>();
}
template <typename TDerived>
inline JsonObject VariantRefBase<TDerived>::createNestedObject() const {
return add().template to<JsonObject>();
}
template <typename TDerived>
inline ElementProxy<TDerived> VariantRefBase<TDerived>::operator[](
size_t index) const {
return ElementProxy<TDerived>(derived(), index);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,117 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Variant/JsonVariant.hpp>
#include <ArduinoJson/Variant/SlotFunctions.hpp>
namespace ARDUINOJSON_NAMESPACE {
class VariantPtr {
public:
VariantPtr(MemoryPool* pool, VariantData* data) : _variant(pool, data) {}
JsonVariant* operator->() {
return &_variant;
}
JsonVariant& operator*() {
return _variant;
}
private:
JsonVariant _variant;
};
class JsonArrayIterator {
friend class JsonArray;
public:
JsonArrayIterator() : _slot(0) {}
explicit JsonArrayIterator(MemoryPool* pool, VariantSlot* slot)
: _pool(pool), _slot(slot) {}
JsonVariant operator*() const {
return JsonVariant(_pool, _slot->data());
}
VariantPtr operator->() {
return VariantPtr(_pool, _slot->data());
}
bool operator==(const JsonArrayIterator& other) const {
return _slot == other._slot;
}
bool operator!=(const JsonArrayIterator& other) const {
return _slot != other._slot;
}
JsonArrayIterator& operator++() {
_slot = _slot->next();
return *this;
}
JsonArrayIterator& operator+=(size_t distance) {
_slot = _slot->next(distance);
return *this;
}
private:
MemoryPool* _pool;
VariantSlot* _slot;
};
class VariantConstPtr {
public:
VariantConstPtr(const VariantData* data) : _variant(data) {}
JsonVariantConst* operator->() {
return &_variant;
}
JsonVariantConst& operator*() {
return _variant;
}
private:
JsonVariantConst _variant;
};
class JsonArrayConstIterator {
friend class JsonArray;
public:
JsonArrayConstIterator() : _slot(0) {}
explicit JsonArrayConstIterator(const VariantSlot* slot) : _slot(slot) {}
JsonVariantConst operator*() const {
return JsonVariantConst(_slot->data());
}
VariantConstPtr operator->() {
return VariantConstPtr(_slot->data());
}
bool operator==(const JsonArrayConstIterator& other) const {
return _slot == other._slot;
}
bool operator!=(const JsonArrayConstIterator& other) const {
return _slot != other._slot;
}
JsonArrayConstIterator& operator++() {
_slot = _slot->next();
return *this;
}
JsonArrayConstIterator& operator+=(size_t distance) {
_slot = _slot->next(distance);
return *this;
}
private:
const VariantSlot* _slot;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -4,19 +4,21 @@
#pragma once
#include <ArduinoJson/Array/ArrayRef.hpp>
#include <ArduinoJson/Array/JsonArray.hpp>
#include <ArduinoJson/Document/JsonDocument.hpp>
namespace ARDUINOJSON_NAMESPACE {
// Trivial form to stop the recursion
// Copies a value to a JsonVariant.
// This is a degenerated form of copyArray() to stop the recursion.
template <typename T>
inline typename enable_if<!is_array<T>::value, bool>::type copyArray(
const T& src, VariantRef dst) {
const T& src, JsonVariant dst) {
return dst.set(src);
}
// Copy array to a JsonArray/JsonVariant/MemberProxy/ElementProxy
// Copies values from an array to a JsonArray or a JsonVariant.
// https://arduinojson.org/v6/api/misc/copyarray/
template <typename T, size_t N, typename TDestination>
inline typename enable_if<!is_base_of<JsonDocument, TDestination>::value,
bool>::type
@@ -24,64 +26,72 @@ copyArray(T (&src)[N], const TDestination& dst) {
return copyArray(src, N, dst);
}
// Copy ptr+size to a JsonArray/JsonVariant/MemberProxy/ElementProxy
// Copies values from an array to a JsonArray or a JsonVariant.
// https://arduinojson.org/v6/api/misc/copyarray/
template <typename T, typename TDestination>
inline typename enable_if<!is_base_of<JsonDocument, TDestination>::value,
bool>::type
copyArray(const T* src, size_t len, const TDestination& dst) {
bool ok = true;
for (size_t i = 0; i < len; i++) {
ok &= copyArray(src[i], dst.addElement());
ok &= copyArray(src[i], dst.add());
}
return ok;
}
// Special case for char[] which much be treated as const char*
// Copies a string to a JsonVariant.
// This is a degenerated form of copyArray() to handle strings.
template <typename TDestination>
inline bool copyArray(const char* src, size_t, const TDestination& dst) {
return dst.set(src);
}
// Copy array to a JsonDocument
// Copies values from an array to a JsonDocument.
// https://arduinojson.org/v6/api/misc/copyarray/
template <typename T>
inline bool copyArray(const T& src, JsonDocument& dst) {
return copyArray(src, dst.to<ArrayRef>());
return copyArray(src, dst.to<JsonArray>());
}
// Copy a ptr+size array to a JsonDocument
// Copies an array to a JsonDocument.
// https://arduinojson.org/v6/api/misc/copyarray/
template <typename T>
inline bool copyArray(const T* src, size_t len, JsonDocument& dst) {
return copyArray(src, len, dst.to<ArrayRef>());
return copyArray(src, len, dst.to<JsonArray>());
}
// Trivial case form to stop the recursion
// Copies a value from a JsonVariant.
// This is a degenerated form of copyArray() to stop the recursion.
template <typename T>
inline typename enable_if<!is_array<T>::value, size_t>::type copyArray(
VariantConstRef src, T& dst) {
JsonVariantConst src, T& dst) {
dst = src.as<T>();
return 1;
}
// Copy a JsonArray to array
// Copies values from a JsonArray or JsonVariant to an array.
// https://arduinojson.org/v6/api/misc/copyarray/
template <typename T, size_t N>
inline size_t copyArray(ArrayConstRef src, T (&dst)[N]) {
inline size_t copyArray(JsonArrayConst src, T (&dst)[N]) {
return copyArray(src, dst, N);
}
// Copy a JsonArray to ptr+size
// Copies values from a JsonArray or JsonVariant to an array.
// https://arduinojson.org/v6/api/misc/copyarray/
template <typename T>
inline size_t copyArray(ArrayConstRef src, T* dst, size_t len) {
inline size_t copyArray(JsonArrayConst src, T* dst, size_t len) {
size_t i = 0;
for (ArrayConstRef::iterator it = src.begin(); it != src.end() && i < len;
for (JsonArrayConst::iterator it = src.begin(); it != src.end() && i < len;
++it)
copyArray(*it, dst[i++]);
return i;
}
// Special case for char[] which must be treated as a string
// Copies a string from a JsonVariant.
// This is a degenerated form of copyArray() to handle strings.
template <size_t N>
inline size_t copyArray(VariantConstRef src, char (&dst)[N]) {
String s = src;
inline size_t copyArray(JsonVariantConst src, char (&dst)[N]) {
JsonString s = src;
size_t len = N - 1;
if (len > s.size())
len = s.size();
@@ -90,14 +100,14 @@ inline size_t copyArray(VariantConstRef src, char (&dst)[N]) {
return 1;
}
// Copy a JsonDocument to an array
// (JsonDocument doesn't implicitly convert to JsonArrayConst)
// Copies values from a JsonDocument to an array.
// https://arduinojson.org/v6/api/misc/copyarray/
template <typename TSource, typename T>
inline typename enable_if<is_array<T>::value &&
is_base_of<JsonDocument, TSource>::value,
size_t>::type
copyArray(const TSource& src, T& dst) {
return copyArray(src.template as<ArrayConstRef>(), dst);
return copyArray(src.template as<JsonArrayConst>(), dst);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -16,8 +16,8 @@ class VariantData;
class VariantSlot;
class CollectionData {
VariantSlot *_head;
VariantSlot *_tail;
VariantSlot* _head;
VariantSlot* _tail;
public:
// Must be a POD!
@@ -28,27 +28,24 @@ class CollectionData {
// Array only
VariantData *addElement(MemoryPool *pool);
VariantData* addElement(MemoryPool* pool);
VariantData *getElement(size_t index) const;
VariantData* getElement(size_t index) const;
VariantData *getOrAddElement(size_t index, MemoryPool *pool);
VariantData* getOrAddElement(size_t index, MemoryPool* pool);
void removeElement(size_t index);
bool equalsArray(const CollectionData &other) const;
// Object only
template <typename TAdaptedString, typename TStoragePolicy>
VariantData *addMember(TAdaptedString key, MemoryPool *pool, TStoragePolicy);
template <typename TAdaptedString>
VariantData* addMember(TAdaptedString key, MemoryPool* pool);
template <typename TAdaptedString>
VariantData *getMember(TAdaptedString key) const;
VariantData* getMember(TAdaptedString key) const;
template <typename TAdaptedString, typename TStoragePolicy>
VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool,
TStoragePolicy);
template <typename TAdaptedString>
VariantData* getOrAddMember(TAdaptedString key, MemoryPool* pool);
template <typename TAdaptedString>
void removeMember(TAdaptedString key) {
@@ -56,34 +53,42 @@ class CollectionData {
}
template <typename TAdaptedString>
bool containsKey(const TAdaptedString &key) const;
bool equalsObject(const CollectionData &other) const;
bool containsKey(const TAdaptedString& key) const;
// Generic
void clear();
size_t memoryUsage() const;
size_t nesting() const;
size_t size() const;
VariantSlot *addSlot(MemoryPool *);
void removeSlot(VariantSlot *slot);
VariantSlot* addSlot(MemoryPool*);
void removeSlot(VariantSlot* slot);
bool copyFrom(const CollectionData &src, MemoryPool *pool);
bool copyFrom(const CollectionData& src, MemoryPool* pool);
VariantSlot *head() const {
VariantSlot* head() const {
return _head;
}
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance);
private:
VariantSlot *getSlot(size_t index) const;
VariantSlot* getSlot(size_t index) const;
template <typename TAdaptedString>
VariantSlot *getSlot(TAdaptedString key) const;
VariantSlot* getSlot(TAdaptedString key) const;
VariantSlot *getPreviousSlot(VariantSlot *) const;
VariantSlot* getPreviousSlot(VariantSlot*) const;
};
inline const VariantData* collectionToVariant(
const CollectionData* collection) {
const void* data = collection; // prevent warning cast-align
return reinterpret_cast<const VariantData*>(data);
}
inline VariantData* collectionToVariant(CollectionData* collection) {
void* data = collection; // prevent warning cast-align
return reinterpret_cast<VariantData*>(data);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -11,16 +11,13 @@
namespace ARDUINOJSON_NAMESPACE {
inline bool variantEquals(const VariantData* a, const VariantData* b) {
return variantCompare(a, b) == COMPARE_RESULT_EQUAL;
}
inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) {
VariantSlot* slot = pool->allocVariant();
if (!slot)
return 0;
if (_tail) {
ARDUINOJSON_ASSERT(pool->owns(_tail)); // Can't alter a linked array/object
_tail->setNextNotNull(slot);
_tail = slot;
} else {
@@ -36,12 +33,11 @@ inline VariantData* CollectionData::addElement(MemoryPool* pool) {
return slotData(addSlot(pool));
}
template <typename TAdaptedString, typename TStoragePolicy>
template <typename TAdaptedString>
inline VariantData* CollectionData::addMember(TAdaptedString key,
MemoryPool* pool,
TStoragePolicy storage) {
MemoryPool* pool) {
VariantSlot* slot = addSlot(pool);
if (!slotSetKey(slot, key, pool, storage)) {
if (!slotSetKey(slot, key, pool)) {
removeSlot(slot);
return 0;
}
@@ -64,8 +60,9 @@ inline bool CollectionData::copyFrom(const CollectionData& src,
for (VariantSlot* s = src._head; s; s = s->next()) {
VariantData* var;
if (s->key() != 0) {
String key(s->key(), s->ownsKey() ? String::Copied : String::Linked);
var = addMember(adaptString(key), pool, getStringStoragePolicy(key));
JsonString key(s->key(),
s->ownsKey() ? JsonString::Copied : JsonString::Linked);
var = addMember(adaptString(key), pool);
} else {
var = addElement(pool);
}
@@ -77,33 +74,6 @@ inline bool CollectionData::copyFrom(const CollectionData& src,
return true;
}
inline bool CollectionData::equalsObject(const CollectionData& other) const {
size_t count = 0;
for (VariantSlot* slot = _head; slot; slot = slot->next()) {
VariantData* v1 = slot->data();
VariantData* v2 = other.getMember(adaptString(slot->key()));
if (!variantEquals(v1, v2))
return false;
count++;
}
return count == other.size();
}
inline bool CollectionData::equalsArray(const CollectionData& other) const {
VariantSlot* s1 = _head;
VariantSlot* s2 = other._head;
for (;;) {
if (s1 == s2)
return true;
if (!s1 || !s2)
return false;
if (!variantEquals(s1->data(), s2->data()))
return false;
s1 = s1->next();
s2 = s2->next();
}
}
template <typename TAdaptedString>
inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const {
if (key.isNull())
@@ -140,9 +110,9 @@ inline VariantData* CollectionData::getMember(TAdaptedString key) const {
return slot ? slot->data() : 0;
}
template <typename TAdaptedString, typename TStoragePolicy>
inline VariantData* CollectionData::getOrAddMember(
TAdaptedString key, MemoryPool* pool, TStoragePolicy storage_policy) {
template <typename TAdaptedString>
inline VariantData* CollectionData::getOrAddMember(TAdaptedString key,
MemoryPool* pool) {
// ignore null key
if (key.isNull())
return 0;
@@ -152,7 +122,7 @@ inline VariantData* CollectionData::getOrAddMember(
if (slot)
return slot->data();
return addMember(key, pool, storage_policy);
return addMember(key, pool);
}
inline VariantData* CollectionData::getElement(size_t index) const {
@@ -203,16 +173,6 @@ inline size_t CollectionData::memoryUsage() const {
return total;
}
inline size_t CollectionData::nesting() const {
size_t maxChildNesting = 0;
for (VariantSlot* s = _head; s; s = s->next()) {
size_t childNesting = s->data()->nesting();
if (childNesting > maxChildNesting)
maxChildNesting = childNesting;
}
return maxChildNesting + 1;
}
inline size_t CollectionData::size() const {
return slotSize(_head);
}

View File

@@ -10,18 +10,18 @@ namespace ARDUINOJSON_NAMESPACE {
class Filter {
public:
explicit Filter(VariantConstRef v) : _variant(v) {}
explicit Filter(JsonVariantConst v) : _variant(v) {}
bool allow() const {
return _variant;
}
bool allowArray() const {
return _variant == true || _variant.is<ArrayConstRef>();
return _variant == true || _variant.is<JsonArrayConst>();
}
bool allowObject() const {
return _variant == true || _variant.is<ObjectConstRef>();
return _variant == true || _variant.is<JsonObjectConst>();
}
bool allowValue() const {
@@ -32,12 +32,12 @@ class Filter {
Filter operator[](const TKey& key) const {
if (_variant == true) // "true" means "allow recursively"
return *this;
VariantConstRef member = _variant[key];
JsonVariantConst member = _variant[key];
return Filter(member.isNull() ? _variant["*"] : member);
}
private:
VariantConstRef _variant;
JsonVariantConst _variant;
};
struct AllowAllFilter {

View File

@@ -23,7 +23,8 @@ class IteratorReader {
size_t readBytes(char* buffer, size_t length) {
size_t i = 0;
while (i < length && _ptr < _end) buffer[i++] = *_ptr++;
while (i < length && _ptr < _end)
buffer[i++] = *_ptr++;
return i;
}
};

View File

@@ -32,7 +32,8 @@ struct Reader<TSource*,
}
size_t readBytes(char* buffer, size_t length) {
for (size_t i = 0; i < length; i++) buffer[i] = *_ptr++;
for (size_t i = 0; i < length; i++)
buffer[i] = *_ptr++;
return length;
}
};

View File

@@ -5,30 +5,15 @@
#pragma once
#include <ArduinoJson/Object/MemberProxy.hpp>
#include <ArduinoJson/Variant/VariantRef.hpp>
#include <ArduinoJson/Variant/JsonVariantConst.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename TArray>
struct Reader<ElementProxy<TArray>, void> : Reader<char*, void> {
explicit Reader(const ElementProxy<TArray>& x)
template <typename TVariant>
struct Reader<TVariant, typename enable_if<IsVariant<TVariant>::value>::type>
: Reader<char*, void> {
explicit Reader(const TVariant& x)
: Reader<char*, void>(x.template as<const char*>()) {}
};
template <typename TObject, typename TStringRef>
struct Reader<MemberProxy<TObject, TStringRef>, void> : Reader<char*, void> {
explicit Reader(const MemberProxy<TObject, TStringRef>& x)
: Reader<char*, void>(x.template as<const char*>()) {}
};
template <>
struct Reader<VariantRef, void> : Reader<char*, void> {
explicit Reader(VariantRef x) : Reader<char*, void>(x.as<const char*>()) {}
};
template <>
struct Reader<VariantConstRef, void> : Reader<char*, void> {
explicit Reader(VariantConstRef x)
: Reader<char*, void>(x.as<const char*>()) {}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -14,9 +14,10 @@ namespace ARDUINOJSON_NAMESPACE {
template <template <typename, typename> class TDeserializer, typename TReader,
typename TWriter>
TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool,
TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool* pool,
TReader reader,
TWriter writer) {
ARDUINOJSON_ASSERT(pool != 0);
return TDeserializer<TReader, TWriter>(pool, reader, writer);
}
@@ -28,14 +29,15 @@ TDeserializer<TReader, TWriter> makeDeserializer(MemoryPool &pool,
template <template <typename, typename> class TDeserializer, typename TString,
typename TFilter>
typename enable_if<!is_array<TString>::value, DeserializationError>::type
deserialize(JsonDocument &doc, const TString &input, NestingLimit nestingLimit,
deserialize(JsonDocument& doc, const TString& input, NestingLimit nestingLimit,
TFilter filter) {
Reader<TString> reader(input);
VariantData* data = VariantAttorney::getData(doc);
MemoryPool* pool = VariantAttorney::getPool(doc);
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), reader,
makeStringStorage(input, doc.memoryPool()))
.parse(doc.data(), filter, nestingLimit);
return makeDeserializer<TDeserializer>(pool, reader,
makeStringStorage(input, pool))
.parse(*data, filter, nestingLimit);
}
//
// deserialize(JsonDocument&, char*, size_t, NestingLimit, Filter);
@@ -43,29 +45,31 @@ deserialize(JsonDocument &doc, const TString &input, NestingLimit nestingLimit,
// deserialize(JsonDocument&, const __FlashStringHelper*, size_t, NL, Filter);
template <template <typename, typename> class TDeserializer, typename TChar,
typename TFilter>
DeserializationError deserialize(JsonDocument &doc, TChar *input,
DeserializationError deserialize(JsonDocument& doc, TChar* input,
size_t inputSize, NestingLimit nestingLimit,
TFilter filter) {
BoundedReader<TChar *> reader(input, inputSize);
BoundedReader<TChar*> reader(input, inputSize);
VariantData* data = VariantAttorney::getData(doc);
MemoryPool* pool = VariantAttorney::getPool(doc);
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), reader,
makeStringStorage(input, doc.memoryPool()))
.parse(doc.data(), filter, nestingLimit);
return makeDeserializer<TDeserializer>(pool, reader,
makeStringStorage(input, pool))
.parse(*data, filter, nestingLimit);
}
//
// deserialize(JsonDocument&, std::istream&, NestingLimit, Filter);
// deserialize(JsonDocument&, Stream&, NestingLimit, Filter);
template <template <typename, typename> class TDeserializer, typename TStream,
typename TFilter>
DeserializationError deserialize(JsonDocument &doc, TStream &input,
DeserializationError deserialize(JsonDocument& doc, TStream& input,
NestingLimit nestingLimit, TFilter filter) {
Reader<TStream> reader(input);
VariantData* data = VariantAttorney::getData(doc);
MemoryPool* pool = VariantAttorney::getPool(doc);
doc.clear();
return makeDeserializer<TDeserializer>(
doc.memoryPool(), reader,
makeStringStorage(input, doc.memoryPool()))
.parse(doc.data(), filter, nestingLimit);
return makeDeserializer<TDeserializer>(pool, reader,
makeStringStorage(input, pool))
.parse(*data, filter, nestingLimit);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -37,6 +37,8 @@ class AllocatorOwner {
TAllocator _allocator;
};
// A JsonDocument that uses the provided allocator to allocate its memory pool.
// https://arduinojson.org/v6/api/basicjsondocument/
template <typename TAllocator>
class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
public:
@@ -65,16 +67,16 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
BasicJsonDocument(
const T& src,
typename enable_if<
is_same<T, VariantRef>::value || is_same<T, VariantConstRef>::value ||
is_same<T, ArrayRef>::value || is_same<T, ArrayConstRef>::value ||
is_same<T, ObjectRef>::value ||
is_same<T, ObjectConstRef>::value>::type* = 0)
is_same<T, JsonVariant>::value ||
is_same<T, JsonVariantConst>::value || is_same<T, JsonArray>::value ||
is_same<T, JsonArrayConst>::value || is_same<T, JsonObject>::value ||
is_same<T, JsonObjectConst>::value>::type* = 0)
: JsonDocument(allocPool(src.memoryUsage())) {
set(src);
}
// disambiguate
BasicJsonDocument(VariantRef src)
BasicJsonDocument(JsonVariant src)
: JsonDocument(allocPool(src.memoryUsage())) {
set(src);
}
@@ -104,6 +106,8 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
return *this;
}
// Reduces the capacity of the memory pool to match the current usage.
// https://arduinojson.org/v6/api/basicjsondocument/shrinktofit/
void shrinkToFit() {
ptrdiff_t bytes_reclaimed = _pool.squash();
if (bytes_reclaimed == 0)
@@ -119,6 +123,8 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
_data.movePointers(ptr_offset, ptr_offset - bytes_reclaimed);
}
// Reclaims the memory leaked when removing and replacing values.
// https://arduinojson.org/v6/api/jsondocument/garbagecollect/
bool garbageCollect() {
// make a temporary clone and move assign
BasicJsonDocument tmp(*this);
@@ -146,7 +152,7 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
}
void freePool() {
this->deallocate(memoryPool().buffer());
this->deallocate(getPool()->buffer());
}
void copyAssignFrom(const JsonDocument& src) {

View File

@@ -10,6 +10,7 @@
namespace ARDUINOJSON_NAMESPACE {
// The allocator of DynamicJsonDocument.
struct DefaultAllocator {
void* allocate(size_t size) {
return malloc(size);
@@ -24,6 +25,8 @@ struct DefaultAllocator {
}
};
// A JsonDocument with a memory pool in the heap.
// https://arduinojson.org/v6/api/dynamicjsondocument/
typedef BasicJsonDocument<DefaultAllocator> DynamicJsonDocument;
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -6,152 +6,169 @@
#include <ArduinoJson/Array/ElementProxy.hpp>
#include <ArduinoJson/Memory/MemoryPool.hpp>
#include <ArduinoJson/Object/JsonObject.hpp>
#include <ArduinoJson/Object/MemberProxy.hpp>
#include <ArduinoJson/Object/ObjectRef.hpp>
#include <ArduinoJson/Strings/StoragePolicy.hpp>
#include <ArduinoJson/Variant/VariantRef.hpp>
#include <ArduinoJson/Variant/JsonVariantConst.hpp>
#include <ArduinoJson/Variant/VariantTo.hpp>
namespace ARDUINOJSON_NAMESPACE {
class JsonDocument : public Visitable,
public VariantOperators<const JsonDocument&> {
public:
template <typename TVisitor>
typename TVisitor::result_type accept(TVisitor& visitor) const {
return getVariant().accept(visitor);
}
// A JSON document.
// https://arduinojson.org/v6/api/jsondocument/
class JsonDocument : public VariantOperators<const JsonDocument&> {
friend class VariantAttorney;
public:
// Casts the root to the specified type.
// https://arduinojson.org/v6/api/jsondocument/as/
template <typename T>
T as() {
return getVariant().template as<T>();
}
// Casts the root to the specified type.
// https://arduinojson.org/v6/api/jsondocument/as/
template <typename T>
T as() const {
return getVariant().template as<T>();
}
// Empties the document and resets the memory pool
// https://arduinojson.org/v6/api/jsondocument/clear/
void clear() {
_pool.clear();
_data.init();
}
// Returns true if the root is of the specified type.
// https://arduinojson.org/v6/api/jsondocument/is/
template <typename T>
bool is() {
return getVariant().template is<T>();
}
// Returns true if the root is of the specified type.
// https://arduinojson.org/v6/api/jsondocument/is/
template <typename T>
bool is() const {
return getVariant().template is<T>();
}
// Returns true if the root is null.
// https://arduinojson.org/v6/api/jsondocument/isnull/
bool isNull() const {
return getVariant().isNull();
}
// Returns the number of used bytes in the memory pool.
// https://arduinojson.org/v6/api/jsondocument/memoryusage/
size_t memoryUsage() const {
return _pool.size();
}
// Returns trues if the memory pool was too small.
// https://arduinojson.org/v6/api/jsondocument/overflowed/
bool overflowed() const {
return _pool.overflowed();
}
// Returns the depth (nesting level) of the array.
// https://arduinojson.org/v6/api/jsondocument/nesting/
size_t nesting() const {
return _data.nesting();
return variantNesting(&_data);
}
// Returns the capacity of the memory pool.
// https://arduinojson.org/v6/api/jsondocument/capacity/
size_t capacity() const {
return _pool.capacity();
}
// Returns the number of elements in the root array or object.
// https://arduinojson.org/v6/api/jsondocument/size/
size_t size() const {
return _data.size();
}
// Copies the specified document.
// https://arduinojson.org/v6/api/jsondocument/set/
bool set(const JsonDocument& src) {
return to<VariantRef>().set(src.as<VariantConstRef>());
return to<JsonVariant>().set(src.as<JsonVariantConst>());
}
// Replaces the root with the specified value.
// https://arduinojson.org/v6/api/jsondocument/set/
template <typename T>
typename enable_if<!is_base_of<JsonDocument, T>::value, bool>::type set(
const T& src) {
return to<VariantRef>().set(src);
return to<JsonVariant>().set(src);
}
// Clears the document and converts it to the specified type.
// https://arduinojson.org/v6/api/jsondocument/to/
template <typename T>
typename VariantTo<T>::type to() {
clear();
return getVariant().template to<T>();
}
// for internal use only
MemoryPool& memoryPool() {
return _pool;
// Creates an array and appends it to the root array.
// https://arduinojson.org/v6/api/jsondocument/createnestedarray/
JsonArray createNestedArray() {
return add().to<JsonArray>();
}
// for internal use only
VariantData& data() {
return _data;
}
ArrayRef createNestedArray() {
return addElement().to<ArrayRef>();
}
// createNestedArray(char*)
// createNestedArray(const char*)
// createNestedArray(const __FlashStringHelper*)
// Creates an array and adds it to the root object.
// https://arduinojson.org/v6/api/jsondocument/createnestedarray/
template <typename TChar>
ArrayRef createNestedArray(TChar* key) {
return getOrAddMember(key).template to<ArrayRef>();
JsonArray createNestedArray(TChar* key) {
return operator[](key).template to<JsonArray>();
}
// createNestedArray(const std::string&)
// createNestedArray(const String&)
// Creates an array and adds it to the root object.
// https://arduinojson.org/v6/api/jsondocument/createnestedarray/
template <typename TString>
ArrayRef createNestedArray(const TString& key) {
return getOrAddMember(key).template to<ArrayRef>();
JsonArray createNestedArray(const TString& key) {
return operator[](key).template to<JsonArray>();
}
ObjectRef createNestedObject() {
return addElement().to<ObjectRef>();
// Creates an object and appends it to the root array.
// https://arduinojson.org/v6/api/jsondocument/createnestedobject/
JsonObject createNestedObject() {
return add().to<JsonObject>();
}
// createNestedObject(char*)
// createNestedObject(const char*)
// createNestedObject(const __FlashStringHelper*)
// Creates an object and adds it to the root object.
// https://arduinojson.org/v6/api/jsondocument/createnestedobject/
template <typename TChar>
ObjectRef createNestedObject(TChar* key) {
return getOrAddMember(key).template to<ObjectRef>();
JsonObject createNestedObject(TChar* key) {
return operator[](key).template to<JsonObject>();
}
// createNestedObject(const std::string&)
// createNestedObject(const String&)
// Creates an object and adds it to the root object.
// https://arduinojson.org/v6/api/jsondocument/createnestedobject/
template <typename TString>
ObjectRef createNestedObject(const TString& key) {
return getOrAddMember(key).template to<ObjectRef>();
JsonObject createNestedObject(const TString& key) {
return operator[](key).template to<JsonObject>();
}
// containsKey(char*) const
// containsKey(const char*) const
// containsKey(const __FlashStringHelper*) const
// Returns true if the root object contains the specified key.
// https://arduinojson.org/v6/api/jsondocument/containskey/
template <typename TChar>
bool containsKey(TChar* key) const {
return !getMember(key).isUnbound();
return _data.getMember(adaptString(key)) != 0;
}
// containsKey(const std::string&) const
// containsKey(const String&) const
// Returns true if the root object contains the specified key.
// https://arduinojson.org/v6/api/jsondocument/containskey/
template <typename TString>
bool containsKey(const TString& key) const {
return !getMember(key).isUnbound();
return _data.getMember(adaptString(key)) != 0;
}
// operator[](const std::string&)
// operator[](const String&)
// Gets or sets a root object's member.
// https://arduinojson.org/v6/api/jsondocument/subscript/
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value,
MemberProxy<JsonDocument&, TString> >::type
@@ -159,9 +176,8 @@ class JsonDocument : public Visitable,
return MemberProxy<JsonDocument&, TString>(*this, key);
}
// operator[](char*)
// operator[](const char*)
// operator[](const __FlashStringHelper*)
// Gets or sets a root object's member.
// https://arduinojson.org/v6/api/jsondocument/subscript/
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value,
MemberProxy<JsonDocument&, TChar*> >::type
@@ -169,138 +185,87 @@ class JsonDocument : public Visitable,
return MemberProxy<JsonDocument&, TChar*>(*this, key);
}
// operator[](const std::string&) const
// operator[](const String&) const
// Gets a root object's member.
// https://arduinojson.org/v6/api/jsondocument/subscript/
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value, VariantConstRef>::type
typename enable_if<IsString<TString>::value, JsonVariantConst>::type
operator[](const TString& key) const {
return getMember(key);
return JsonVariantConst(_data.getMember(adaptString(key)));
}
// operator[](char*) const
// operator[](const char*) const
// operator[](const __FlashStringHelper*) const
// Gets a root object's member.
// https://arduinojson.org/v6/api/jsondocument/subscript/
template <typename TChar>
FORCE_INLINE
typename enable_if<IsString<TChar*>::value, VariantConstRef>::type
typename enable_if<IsString<TChar*>::value, JsonVariantConst>::type
operator[](TChar* key) const {
return getMember(key);
return JsonVariantConst(_data.getMember(adaptString(key)));
}
// Gets or sets a root array's element.
// https://arduinojson.org/v6/api/jsondocument/subscript/
FORCE_INLINE ElementProxy<JsonDocument&> operator[](size_t index) {
return ElementProxy<JsonDocument&>(*this, index);
}
FORCE_INLINE VariantConstRef operator[](size_t index) const {
return getElement(index);
// Gets a root array's member.
// https://arduinojson.org/v6/api/jsondocument/subscript/
FORCE_INLINE JsonVariantConst operator[](size_t index) const {
return JsonVariantConst(_data.getElement(index));
}
FORCE_INLINE VariantRef getElement(size_t index) {
return VariantRef(&_pool, _data.getElement(index));
}
FORCE_INLINE VariantConstRef getElement(size_t index) const {
return VariantConstRef(_data.getElement(index));
}
FORCE_INLINE VariantRef getOrAddElement(size_t index) {
return VariantRef(&_pool, _data.getOrAddElement(index, &_pool));
}
// JsonVariantConst getMember(char*) const
// JsonVariantConst getMember(const char*) const
// JsonVariantConst getMember(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantConstRef getMember(TChar* key) const {
return VariantConstRef(_data.getMember(adaptString(key)));
}
// JsonVariantConst getMember(const std::string&) const
// JsonVariantConst getMember(const String&) const
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value, VariantConstRef>::type
getMember(const TString& key) const {
return VariantConstRef(_data.getMember(adaptString(key)));
}
// JsonVariant getMember(char*)
// JsonVariant getMember(const char*)
// JsonVariant getMember(const __FlashStringHelper*)
template <typename TChar>
FORCE_INLINE VariantRef getMember(TChar* key) {
return VariantRef(&_pool, _data.getMember(adaptString(key)));
}
// JsonVariant getMember(const std::string&)
// JsonVariant getMember(const String&)
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type
getMember(const TString& key) {
return VariantRef(&_pool, _data.getMember(adaptString(key)));
}
// getOrAddMember(char*)
// getOrAddMember(const char*)
// getOrAddMember(const __FlashStringHelper*)
template <typename TChar>
FORCE_INLINE VariantRef getOrAddMember(TChar* key) {
return VariantRef(&_pool,
_data.getOrAddMember(adaptString(key), &_pool,
getStringStoragePolicy(key)));
}
// getOrAddMember(const std::string&)
// getOrAddMember(const String&)
template <typename TString>
FORCE_INLINE VariantRef getOrAddMember(const TString& key) {
return VariantRef(&_pool,
_data.getOrAddMember(adaptString(key), &_pool,
getStringStoragePolicy(key)));
}
FORCE_INLINE VariantRef addElement() {
return VariantRef(&_pool, _data.addElement(&_pool));
// Appends a new (null) element to the root array.
// Returns a reference to the new element.
// https://arduinojson.org/v6/api/jsondocument/add/
FORCE_INLINE JsonVariant add() {
return JsonVariant(&_pool, _data.addElement(&_pool));
}
// Appends a value to the root array.
// https://arduinojson.org/v6/api/jsondocument/add/
template <typename TValue>
FORCE_INLINE bool add(const TValue& value) {
return addElement().set(value);
return add().set(value);
}
// add(char*) const
// add(const char*) const
// add(const __FlashStringHelper*) const
// Appends a value to the root array.
// https://arduinojson.org/v6/api/jsondocument/add/
template <typename TChar>
FORCE_INLINE bool add(TChar* value) {
return addElement().set(value);
return add().set(value);
}
// Removes an element of the root array.
// ⚠️ Doesn't release the memory associated with the removed element.
// https://arduinojson.org/v6/api/jsondocument/remove/
FORCE_INLINE void remove(size_t index) {
_data.remove(index);
}
// remove(char*)
// remove(const char*)
// remove(const __FlashStringHelper*)
// Removes a member of the root object.
// ⚠️ Doesn't release the memory associated with the removed element.
// https://arduinojson.org/v6/api/jsondocument/remove/
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove(
TChar* key) {
_data.remove(adaptString(key));
}
// remove(const std::string&)
// remove(const String&)
// Removes a member of the root object.
// ⚠️ Doesn't release the memory associated with the removed element.
// https://arduinojson.org/v6/api/jsondocument/remove/
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
const TString& key) {
_data.remove(adaptString(key));
}
FORCE_INLINE operator VariantRef() {
FORCE_INLINE operator JsonVariant() {
return getVariant();
}
FORCE_INLINE operator VariantConstRef() const {
FORCE_INLINE operator JsonVariantConst() const {
return getVariant();
}
@@ -323,12 +288,12 @@ class JsonDocument : public Visitable,
_pool = pool;
}
VariantRef getVariant() {
return VariantRef(&_pool, &_data);
JsonVariant getVariant() {
return JsonVariant(&_pool, &_data);
}
VariantConstRef getVariant() const {
return VariantConstRef(&_data);
JsonVariantConst getVariant() const {
return JsonVariantConst(&_data);
}
MemoryPool _pool;
@@ -337,10 +302,27 @@ class JsonDocument : public Visitable,
private:
JsonDocument(const JsonDocument&);
JsonDocument& operator=(const JsonDocument&);
protected:
MemoryPool* getPool() {
return &_pool;
}
VariantData* getData() {
return &_data;
}
const VariantData* getData() const {
return &_data;
}
VariantData* getOrCreateData() {
return &_data;
}
};
inline void convertToJson(const JsonDocument& src, VariantRef dst) {
dst.set(src.as<VariantConstRef>());
inline void convertToJson(const JsonDocument& src, JsonVariant dst) {
dst.set(src.as<JsonVariantConst>());
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -8,6 +8,7 @@
namespace ARDUINOJSON_NAMESPACE {
// A JsonDocument with a memory pool on the stack.
template <size_t desiredCapacity>
class StaticJsonDocument : public JsonDocument {
static const size_t _capacity =
@@ -22,14 +23,15 @@ class StaticJsonDocument : public JsonDocument {
}
template <typename T>
StaticJsonDocument(const T& src,
typename enable_if<IsVisitable<T>::value>::type* = 0)
StaticJsonDocument(
const T& src,
typename enable_if<is_convertible<T, JsonVariantConst>::value>::type* = 0)
: JsonDocument(_buffer, _capacity) {
set(src);
}
// disambiguate
StaticJsonDocument(VariantRef src) : JsonDocument(_buffer, _capacity) {
StaticJsonDocument(JsonVariant src) : JsonDocument(_buffer, _capacity) {
set(src);
}
@@ -44,6 +46,8 @@ class StaticJsonDocument : public JsonDocument {
return *this;
}
// Reclaims the memory leaked when removing and replacing values.
// https://arduinojson.org/v6/api/jsondocument/garbagecollect/
void garbageCollect() {
StaticJsonDocument tmp(*this);
set(tmp);

View File

@@ -12,7 +12,7 @@ class EscapeSequence {
public:
// Optimized for code size on a 8-bit AVR
static char escapeChar(char c) {
const char *p = escapeTable(true);
const char* p = escapeTable(true);
while (p[0] && p[1] != c) {
p += 2;
}
@@ -21,7 +21,7 @@ class EscapeSequence {
// Optimized for code size on a 8-bit AVR
static char unescapeChar(char c) {
const char *p = escapeTable(false);
const char* p = escapeTable(false);
for (;;) {
if (p[0] == '\0')
return 0;
@@ -32,7 +32,7 @@ class EscapeSequence {
}
private:
static const char *escapeTable(bool excludeSolidus) {
static const char* escapeTable(bool excludeSolidus) {
return &"//\"\"\\\\b\bf\fn\nr\rt\t"[excludeSolidus ? 2 : 0];
}
};

View File

@@ -20,25 +20,26 @@ namespace ARDUINOJSON_NAMESPACE {
template <typename TReader, typename TStringStorage>
class JsonDeserializer {
public:
JsonDeserializer(MemoryPool &pool, TReader reader,
JsonDeserializer(MemoryPool* pool, TReader reader,
TStringStorage stringStorage)
: _stringStorage(stringStorage),
_foundSomething(false),
_latch(reader),
_pool(&pool),
_error(DeserializationError::Ok) {}
_pool(pool) {}
template <typename TFilter>
DeserializationError parse(VariantData &variant, TFilter filter,
DeserializationError parse(VariantData& variant, TFilter filter,
NestingLimit nestingLimit) {
parseVariant(variant, filter, nestingLimit);
DeserializationError::Code err;
if (!_error && _latch.last() != 0 && !variant.isEnclosed()) {
err = parseVariant(variant, filter, nestingLimit);
if (!err && _latch.last() != 0 && !variant.isEnclosed()) {
// We don't detect trailing characters earlier, so we need to check now
return DeserializationError::InvalidInput;
}
return _error;
return err;
}
private:
@@ -58,10 +59,13 @@ class JsonDeserializer {
}
template <typename TFilter>
bool parseVariant(VariantData &variant, TFilter filter,
NestingLimit nestingLimit) {
if (!skipSpacesAndComments())
return false;
DeserializationError::Code parseVariant(VariantData& variant, TFilter filter,
NestingLimit nestingLimit) {
DeserializationError::Code err;
err = skipSpacesAndComments();
if (err)
return err;
switch (current()) {
case '[':
@@ -81,7 +85,22 @@ class JsonDeserializer {
if (filter.allowValue())
return parseStringValue(variant);
else
return skipString();
return skipQuotedString();
case 't':
if (filter.allowValue())
variant.setBoolean(true);
return skipKeyword("true");
case 'f':
if (filter.allowValue())
variant.setBoolean(false);
return skipKeyword("false");
case 'n':
// the variant should already by null, except if the same object key was
// used twice, as in {"a":1,"a":null}
return skipKeyword("null");
default:
if (filter.allowValue())
@@ -91,9 +110,12 @@ class JsonDeserializer {
}
}
bool skipVariant(NestingLimit nestingLimit) {
if (!skipSpacesAndComments())
return false;
DeserializationError::Code skipVariant(NestingLimit nestingLimit) {
DeserializationError::Code err;
err = skipSpacesAndComments();
if (err)
return err;
switch (current()) {
case '[':
@@ -104,7 +126,16 @@ class JsonDeserializer {
case '\"':
case '\'':
return skipString();
return skipQuotedString();
case 't':
return skipKeyword("true");
case 'f':
return skipKeyword("false");
case 'n':
return skipKeyword("null");
default:
return skipNumericValue();
@@ -112,24 +143,25 @@ class JsonDeserializer {
}
template <typename TFilter>
bool parseArray(CollectionData &array, TFilter filter,
NestingLimit nestingLimit) {
if (nestingLimit.reached()) {
_error = DeserializationError::TooDeep;
return false;
}
DeserializationError::Code parseArray(CollectionData& array, TFilter filter,
NestingLimit nestingLimit) {
DeserializationError::Code err;
if (nestingLimit.reached())
return DeserializationError::TooDeep;
// Skip opening braket
ARDUINOJSON_ASSERT(current() == '[');
move();
// Skip spaces
if (!skipSpacesAndComments())
return false;
err = skipSpacesAndComments();
if (err)
return err;
// Empty array?
if (eat(']'))
return true;
return DeserializationError::Ok;
TFilter memberFilter = filter[0UL];
@@ -137,39 +169,38 @@ class JsonDeserializer {
for (;;) {
if (memberFilter.allow()) {
// Allocate slot in array
VariantData *value = array.addElement(_pool);
if (!value) {
_error = DeserializationError::NoMemory;
return false;
}
VariantData* value = array.addElement(_pool);
if (!value)
return DeserializationError::NoMemory;
// 1 - Parse value
if (!parseVariant(*value, memberFilter, nestingLimit.decrement()))
return false;
err = parseVariant(*value, memberFilter, nestingLimit.decrement());
if (err)
return err;
} else {
if (!skipVariant(nestingLimit.decrement()))
return false;
err = skipVariant(nestingLimit.decrement());
if (err)
return err;
}
// 2 - Skip spaces
if (!skipSpacesAndComments())
return false;
err = skipSpacesAndComments();
if (err)
return err;
// 3 - More values?
if (eat(']'))
return true;
if (!eat(',')) {
_error = DeserializationError::InvalidInput;
return false;
}
return DeserializationError::Ok;
if (!eat(','))
return DeserializationError::InvalidInput;
}
}
bool skipArray(NestingLimit nestingLimit) {
if (nestingLimit.reached()) {
_error = DeserializationError::TooDeep;
return false;
}
DeserializationError::Code skipArray(NestingLimit nestingLimit) {
DeserializationError::Code err;
if (nestingLimit.reached())
return DeserializationError::TooDeep;
// Skip opening braket
ARDUINOJSON_ASSERT(current() == '[');
@@ -178,76 +209,75 @@ class JsonDeserializer {
// Read each value
for (;;) {
// 1 - Skip value
if (!skipVariant(nestingLimit.decrement()))
return false;
err = skipVariant(nestingLimit.decrement());
if (err)
return err;
// 2 - Skip spaces
if (!skipSpacesAndComments())
return false;
err = skipSpacesAndComments();
if (err)
return err;
// 3 - More values?
if (eat(']'))
return true;
if (!eat(',')) {
_error = DeserializationError::InvalidInput;
return false;
}
return DeserializationError::Ok;
if (!eat(','))
return DeserializationError::InvalidInput;
}
}
template <typename TFilter>
bool parseObject(CollectionData &object, TFilter filter,
NestingLimit nestingLimit) {
if (nestingLimit.reached()) {
_error = DeserializationError::TooDeep;
return false;
}
DeserializationError::Code parseObject(CollectionData& object, TFilter filter,
NestingLimit nestingLimit) {
DeserializationError::Code err;
if (nestingLimit.reached())
return DeserializationError::TooDeep;
// Skip opening brace
ARDUINOJSON_ASSERT(current() == '{');
move();
// Skip spaces
if (!skipSpacesAndComments())
return false;
err = skipSpacesAndComments();
if (err)
return err;
// Empty object?
if (eat('}'))
return true;
return DeserializationError::Ok;
// Read each key value pair
for (;;) {
// Parse key
if (!parseKey())
return false;
err = parseKey();
if (err)
return err;
// Skip spaces
if (!skipSpacesAndComments())
return false;
err = skipSpacesAndComments();
if (err)
return err;
// Colon
if (!eat(':')) {
_error = DeserializationError::InvalidInput;
return false;
}
if (!eat(':'))
return DeserializationError::InvalidInput;
String key = _stringStorage.str();
JsonString key = _stringStorage.str();
TFilter memberFilter = filter[key.c_str()];
if (memberFilter.allow()) {
VariantData *variant = object.getMember(adaptString(key.c_str()));
VariantData* variant = object.getMember(adaptString(key.c_str()));
if (!variant) {
// Save key in memory pool.
// This MUST be done before adding the slot.
key = _stringStorage.save();
// Allocate slot in object
VariantSlot *slot = object.addSlot(_pool);
if (!slot) {
_error = DeserializationError::NoMemory;
return false;
}
VariantSlot* slot = object.addSlot(_pool);
if (!slot)
return DeserializationError::NoMemory;
slot->setKey(key);
@@ -255,84 +285,91 @@ class JsonDeserializer {
}
// Parse value
if (!parseVariant(*variant, memberFilter, nestingLimit.decrement()))
return false;
err = parseVariant(*variant, memberFilter, nestingLimit.decrement());
if (err)
return err;
} else {
if (!skipVariant(nestingLimit.decrement()))
return false;
err = skipVariant(nestingLimit.decrement());
if (err)
return err;
}
// Skip spaces
if (!skipSpacesAndComments())
return false;
err = skipSpacesAndComments();
if (err)
return err;
// More keys/values?
if (eat('}'))
return true;
if (!eat(',')) {
_error = DeserializationError::InvalidInput;
return false;
}
return DeserializationError::Ok;
if (!eat(','))
return DeserializationError::InvalidInput;
// Skip spaces
if (!skipSpacesAndComments())
return false;
err = skipSpacesAndComments();
if (err)
return err;
}
}
bool skipObject(NestingLimit nestingLimit) {
if (nestingLimit.reached()) {
_error = DeserializationError::TooDeep;
return false;
}
DeserializationError::Code skipObject(NestingLimit nestingLimit) {
DeserializationError::Code err;
if (nestingLimit.reached())
return DeserializationError::TooDeep;
// Skip opening brace
ARDUINOJSON_ASSERT(current() == '{');
move();
// Skip spaces
if (!skipSpacesAndComments())
return false;
err = skipSpacesAndComments();
if (err)
return err;
// Empty object?
if (eat('}'))
return true;
return DeserializationError::Ok;
// Read each key value pair
for (;;) {
// Skip key
if (!skipVariant(nestingLimit.decrement()))
return false;
err = skipKey();
if (err)
return err;
// Skip spaces
if (!skipSpacesAndComments())
return false;
err = skipSpacesAndComments();
if (err)
return err;
// Colon
if (!eat(':')) {
_error = DeserializationError::InvalidInput;
return false;
}
if (!eat(':'))
return DeserializationError::InvalidInput;
// Skip value
if (!skipVariant(nestingLimit.decrement()))
return false;
err = skipVariant(nestingLimit.decrement());
if (err)
return err;
// Skip spaces
if (!skipSpacesAndComments())
return false;
err = skipSpacesAndComments();
if (err)
return err;
// More keys/values?
if (eat('}'))
return true;
if (!eat(',')) {
_error = DeserializationError::InvalidInput;
return false;
}
return DeserializationError::Ok;
if (!eat(','))
return DeserializationError::InvalidInput;
err = skipSpacesAndComments();
if (err)
return err;
}
}
bool parseKey() {
DeserializationError::Code parseKey() {
_stringStorage.startString();
if (isQuote(current())) {
return parseQuotedString();
@@ -341,17 +378,24 @@ class JsonDeserializer {
}
}
bool parseStringValue(VariantData &variant) {
DeserializationError::Code parseStringValue(VariantData& variant) {
DeserializationError::Code err;
_stringStorage.startString();
if (!parseQuotedString())
return false;
err = parseQuotedString();
if (err)
return err;
variant.setString(_stringStorage.save());
return true;
return DeserializationError::Ok;
}
bool parseQuotedString() {
DeserializationError::Code parseQuotedString() {
#if ARDUINOJSON_DECODE_UNICODE
Utf16::Codepoint codepoint;
DeserializationError::Code err;
#endif
const char stopChar = current();
@@ -362,25 +406,22 @@ class JsonDeserializer {
if (c == stopChar)
break;
if (c == '\0') {
_error = DeserializationError::IncompleteInput;
return false;
}
if (c == '\0')
return DeserializationError::IncompleteInput;
if (c == '\\') {
c = current();
if (c == '\0') {
_error = DeserializationError::IncompleteInput;
return false;
}
if (c == '\0')
return DeserializationError::IncompleteInput;
if (c == 'u') {
#if ARDUINOJSON_DECODE_UNICODE
move();
uint16_t codeunit;
if (!parseHex4(codeunit))
return false;
err = parseHex4(codeunit);
if (err)
return err;
if (codepoint.append(codeunit))
Utf8::encodeCodepoint(codepoint.value(), _stringStorage);
#else
@@ -391,25 +432,21 @@ class JsonDeserializer {
// replace char
c = EscapeSequence::unescapeChar(c);
if (c == '\0') {
_error = DeserializationError::InvalidInput;
return false;
}
if (c == '\0')
return DeserializationError::InvalidInput;
move();
}
_stringStorage.append(c);
}
if (!_stringStorage.isValid()) {
_error = DeserializationError::NoMemory;
return false;
}
if (!_stringStorage.isValid())
return DeserializationError::NoMemory;
return true;
return DeserializationError::Ok;
}
bool parseNonQuotedString() {
DeserializationError::Code parseNonQuotedString() {
char c = current();
ARDUINOJSON_ASSERT(c);
@@ -420,19 +457,24 @@ class JsonDeserializer {
c = current();
} while (canBeInNonQuotedString(c));
} else {
_error = DeserializationError::InvalidInput;
return false;
return DeserializationError::InvalidInput;
}
if (!_stringStorage.isValid()) {
_error = DeserializationError::NoMemory;
return false;
}
if (!_stringStorage.isValid())
return DeserializationError::NoMemory;
return true;
return DeserializationError::Ok;
}
bool skipString() {
DeserializationError::Code skipKey() {
if (isQuote(current())) {
return skipQuotedString();
} else {
return skipNonQuotedString();
}
}
DeserializationError::Code skipQuotedString() {
const char stopChar = current();
move();
@@ -441,99 +483,83 @@ class JsonDeserializer {
move();
if (c == stopChar)
break;
if (c == '\0') {
_error = DeserializationError::IncompleteInput;
return false;
}
if (c == '\0')
return DeserializationError::IncompleteInput;
if (c == '\\') {
if (current() != '\0')
move();
}
}
return true;
return DeserializationError::Ok;
}
bool parseNumericValue(VariantData &result) {
DeserializationError::Code skipNonQuotedString() {
char c = current();
while (canBeInNonQuotedString(c)) {
move();
c = current();
}
return DeserializationError::Ok;
}
DeserializationError::Code parseNumericValue(VariantData& result) {
uint8_t n = 0;
char c = current();
while (canBeInNonQuotedString(c) && n < 63) {
while (canBeInNumber(c) && n < 63) {
move();
_buffer[n++] = c;
c = current();
}
_buffer[n] = 0;
c = _buffer[0];
if (c == 't') { // true
result.setBoolean(true);
if (n != 4) {
_error = DeserializationError::IncompleteInput;
return false;
}
return true;
}
if (c == 'f') { // false
result.setBoolean(false);
if (n != 5) {
_error = DeserializationError::IncompleteInput;
return false;
}
return true;
}
if (c == 'n') { // null
// the variant is already null
if (n != 4) {
_error = DeserializationError::IncompleteInput;
return false;
}
return true;
}
if (!parseNumber(_buffer, result))
return DeserializationError::InvalidInput;
if (!parseNumber(_buffer, result)) {
_error = DeserializationError::InvalidInput;
return false;
}
return true;
return DeserializationError::Ok;
}
bool skipNumericValue() {
DeserializationError::Code skipNumericValue() {
char c = current();
while (canBeInNonQuotedString(c)) {
while (canBeInNumber(c)) {
move();
c = current();
}
return true;
return DeserializationError::Ok;
}
bool parseHex4(uint16_t &result) {
DeserializationError::Code parseHex4(uint16_t& result) {
result = 0;
for (uint8_t i = 0; i < 4; ++i) {
char digit = current();
if (!digit) {
_error = DeserializationError::IncompleteInput;
return false;
}
if (!digit)
return DeserializationError::IncompleteInput;
uint8_t value = decodeHex(digit);
if (value > 0x0F) {
_error = DeserializationError::InvalidInput;
return false;
}
if (value > 0x0F)
return DeserializationError::InvalidInput;
result = uint16_t((result << 4) | value);
move();
}
return true;
return DeserializationError::Ok;
}
static inline bool isBetween(char c, char min, char max) {
return min <= c && c <= max;
}
static inline bool canBeInNumber(char c) {
return isBetween(c, '0', '9') || c == '+' || c == '-' || c == '.' ||
#if ARDUINOJSON_ENABLE_NAN || ARDUINOJSON_ENABLE_INFINITY
isBetween(c, 'A', 'Z') || isBetween(c, 'a', 'z');
#else
c == 'e' || c == 'E';
#endif
}
static inline bool canBeInNonQuotedString(char c) {
return isBetween(c, '0', '9') || isBetween(c, '_', 'z') ||
isBetween(c, 'A', 'Z') || c == '+' || c == '-' || c == '.';
isBetween(c, 'A', 'Z');
}
static inline bool isQuote(char c) {
@@ -547,14 +573,13 @@ class JsonDeserializer {
return uint8_t(c - 'A' + 10);
}
bool skipSpacesAndComments() {
DeserializationError::Code skipSpacesAndComments() {
for (;;) {
switch (current()) {
// end of string
case '\0':
_error = _foundSomething ? DeserializationError::IncompleteInput
: DeserializationError::EmptyInput;
return false;
return _foundSomething ? DeserializationError::IncompleteInput
: DeserializationError::EmptyInput;
// spaces
case ' ':
@@ -575,10 +600,8 @@ class JsonDeserializer {
bool wasStar = false;
for (;;) {
char c = current();
if (c == '\0') {
_error = DeserializationError::IncompleteInput;
return false;
}
if (c == '\0')
return DeserializationError::IncompleteInput;
if (c == '/' && wasStar) {
move();
break;
@@ -595,10 +618,8 @@ class JsonDeserializer {
for (;;) {
move();
char c = current();
if (c == '\0') {
_error = DeserializationError::IncompleteInput;
return false;
}
if (c == '\0')
return DeserializationError::IncompleteInput;
if (c == '\n')
break;
}
@@ -606,126 +627,145 @@ class JsonDeserializer {
// not a comment, just a '/'
default:
_error = DeserializationError::InvalidInput;
return false;
return DeserializationError::InvalidInput;
}
break;
#endif
default:
_foundSomething = true;
return true;
return DeserializationError::Ok;
}
}
}
DeserializationError::Code skipKeyword(const char* s) {
while (*s) {
char c = current();
if (c == '\0')
return DeserializationError::IncompleteInput;
if (*s != c)
return DeserializationError::InvalidInput;
++s;
move();
}
return DeserializationError::Ok;
}
TStringStorage _stringStorage;
bool _foundSomething;
Latch<TReader> _latch;
MemoryPool *_pool;
MemoryPool* _pool;
char _buffer[64]; // using a member instead of a local variable because it
// ended in the recursive path after compiler inlined the
// code
DeserializationError _error;
};
//
// deserializeJson(JsonDocument&, const std::string&, ...)
//
// ... = NestingLimit
// Parses a JSON input and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/json/deserializejson/
template <typename TString>
DeserializationError deserializeJson(
JsonDocument &doc, const TString &input,
JsonDocument& doc, const TString& input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, nestingLimit,
AllowAllFilter());
}
// ... = Filter, NestingLimit
// Parses a JSON input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/json/deserializejson/
template <typename TString>
DeserializationError deserializeJson(
JsonDocument &doc, const TString &input, Filter filter,
JsonDocument& doc, const TString& input, Filter filter,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
}
// ... = NestingLimit, Filter
// Parses a JSON input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/json/deserializejson/
template <typename TString>
DeserializationError deserializeJson(JsonDocument &doc, const TString &input,
DeserializationError deserializeJson(JsonDocument& doc, const TString& input,
NestingLimit nestingLimit, Filter filter) {
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
}
//
// deserializeJson(JsonDocument&, std::istream&, ...)
//
// ... = NestingLimit
// Parses a JSON input and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/json/deserializejson/
template <typename TStream>
DeserializationError deserializeJson(
JsonDocument &doc, TStream &input,
JsonDocument& doc, TStream& input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, nestingLimit,
AllowAllFilter());
}
// ... = Filter, NestingLimit
// Parses a JSON input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/json/deserializejson/
template <typename TStream>
DeserializationError deserializeJson(
JsonDocument &doc, TStream &input, Filter filter,
JsonDocument& doc, TStream& input, Filter filter,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
}
// ... = NestingLimit, Filter
// Parses a JSON input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/json/deserializejson/
template <typename TStream>
DeserializationError deserializeJson(JsonDocument &doc, TStream &input,
DeserializationError deserializeJson(JsonDocument& doc, TStream& input,
NestingLimit nestingLimit, Filter filter) {
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
}
//
// deserializeJson(JsonDocument&, char*, ...)
//
// ... = NestingLimit
// Parses a JSON input and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/json/deserializejson/
template <typename TChar>
DeserializationError deserializeJson(
JsonDocument &doc, TChar *input,
JsonDocument& doc, TChar* input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, nestingLimit,
AllowAllFilter());
}
// ... = Filter, NestingLimit
// Parses a JSON input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/json/deserializejson/
template <typename TChar>
DeserializationError deserializeJson(
JsonDocument &doc, TChar *input, Filter filter,
JsonDocument& doc, TChar* input, Filter filter,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
}
// ... = NestingLimit, Filter
// Parses a JSON input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/json/deserializejson/
template <typename TChar>
DeserializationError deserializeJson(JsonDocument &doc, TChar *input,
DeserializationError deserializeJson(JsonDocument& doc, TChar* input,
NestingLimit nestingLimit, Filter filter) {
return deserialize<JsonDeserializer>(doc, input, nestingLimit, filter);
}
//
// deserializeJson(JsonDocument&, char*, size_t, ...)
//
// ... = NestingLimit
// Parses a JSON input and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/json/deserializejson/
template <typename TChar>
DeserializationError deserializeJson(
JsonDocument &doc, TChar *input, size_t inputSize,
JsonDocument& doc, TChar* input, size_t inputSize,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit,
AllowAllFilter());
}
// ... = Filter, NestingLimit
// Parses a JSON input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/json/deserializejson/
template <typename TChar>
DeserializationError deserializeJson(
JsonDocument &doc, TChar *input, size_t inputSize, Filter filter,
JsonDocument& doc, TChar* input, size_t inputSize, Filter filter,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit,
filter);
}
// ... = NestingLimit, Filter
// Parses a JSON input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/json/deserializejson/
template <typename TChar>
DeserializationError deserializeJson(JsonDocument &doc, TChar *input,
DeserializationError deserializeJson(JsonDocument& doc, TChar* input,
size_t inputSize,
NestingLimit nestingLimit, Filter filter) {
return deserialize<JsonDeserializer>(doc, input, inputSize, nestingLimit,

View File

@@ -5,7 +5,6 @@
#pragma once
#include <ArduinoJson/Json/TextFormatter.hpp>
#include <ArduinoJson/Misc/Visitable.hpp>
#include <ArduinoJson/Serialization/measure.hpp>
#include <ArduinoJson/Serialization/serialize.hpp>
#include <ArduinoJson/Variant/Visitor.hpp>
@@ -19,10 +18,10 @@ class JsonSerializer : public Visitor<size_t> {
JsonSerializer(TWriter writer) : _formatter(writer) {}
FORCE_INLINE size_t visitArray(const CollectionData &array) {
FORCE_INLINE size_t visitArray(const CollectionData& array) {
write('[');
VariantSlot *slot = array.head();
const VariantSlot* slot = array.head();
while (slot != 0) {
slot->data()->accept(*this);
@@ -38,10 +37,10 @@ class JsonSerializer : public Visitor<size_t> {
return bytesWritten();
}
size_t visitObject(const CollectionData &object) {
size_t visitObject(const CollectionData& object) {
write('{');
VariantSlot *slot = object.head();
const VariantSlot* slot = object.head();
while (slot != 0) {
_formatter.writeString(slot->key());
@@ -59,32 +58,32 @@ class JsonSerializer : public Visitor<size_t> {
return bytesWritten();
}
size_t visitFloat(Float value) {
size_t visitFloat(JsonFloat value) {
_formatter.writeFloat(value);
return bytesWritten();
}
size_t visitString(const char *value) {
size_t visitString(const char* value) {
_formatter.writeString(value);
return bytesWritten();
}
size_t visitString(const char *value, size_t n) {
size_t visitString(const char* value, size_t n) {
_formatter.writeString(value, n);
return bytesWritten();
}
size_t visitRawJson(const char *data, size_t n) {
size_t visitRawJson(const char* data, size_t n) {
_formatter.writeRaw(data, n);
return bytesWritten();
}
size_t visitSignedInteger(Integer value) {
size_t visitSignedInteger(JsonInteger value) {
_formatter.writeInteger(value);
return bytesWritten();
}
size_t visitUnsignedInteger(UInt value) {
size_t visitUnsignedInteger(JsonUInt value) {
_formatter.writeInteger(value);
return bytesWritten();
}
@@ -108,7 +107,7 @@ class JsonSerializer : public Visitor<size_t> {
_formatter.writeRaw(c);
}
void write(const char *s) {
void write(const char* s) {
_formatter.writeRaw(s);
}
@@ -116,25 +115,31 @@ class JsonSerializer : public Visitor<size_t> {
TextFormatter<TWriter> _formatter;
};
template <typename TSource, typename TDestination>
size_t serializeJson(const TSource &source, TDestination &destination) {
// Produces a minified JSON document.
// https://arduinojson.org/v6/api/json/serializejson/
template <typename TDestination>
size_t serializeJson(JsonVariantConst source, TDestination& destination) {
return serialize<JsonSerializer>(source, destination);
}
template <typename TSource>
size_t serializeJson(const TSource &source, void *buffer, size_t bufferSize) {
// Produces a minified JSON document.
// https://arduinojson.org/v6/api/json/serializejson/
inline size_t serializeJson(JsonVariantConst source, void* buffer,
size_t bufferSize) {
return serialize<JsonSerializer>(source, buffer, bufferSize);
}
template <typename TSource>
size_t measureJson(const TSource &source) {
// Computes the length of the document that serializeJson() produces.
// https://arduinojson.org/v6/api/json/measurejson/
inline size_t measureJson(JsonVariantConst source) {
return measure<JsonSerializer>(source);
}
#if ARDUINOJSON_ENABLE_STD_STREAM
template <typename T>
inline typename enable_if<IsVisitable<T>::value, std::ostream &>::type
operator<<(std::ostream &os, const T &source) {
inline typename enable_if<is_convertible<T, JsonVariantConst>::value,
std::ostream&>::type
operator<<(std::ostream& os, const T& source) {
serializeJson(source, os);
return os;
}

View File

@@ -18,8 +18,8 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
public:
PrettyJsonSerializer(TWriter writer) : base(writer), _nesting(0) {}
size_t visitArray(const CollectionData &array) {
VariantSlot *slot = array.head();
size_t visitArray(const CollectionData& array) {
const VariantSlot* slot = array.head();
if (slot) {
base::write("[\r\n");
_nesting++;
@@ -39,8 +39,8 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
return this->bytesWritten();
}
size_t visitObject(const CollectionData &object) {
VariantSlot *slot = object.head();
size_t visitObject(const CollectionData& object) {
const VariantSlot* slot = object.head();
if (slot) {
base::write("{\r\n");
_nesting++;
@@ -64,25 +64,30 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
private:
void indent() {
for (uint8_t i = 0; i < _nesting; i++) base::write(ARDUINOJSON_TAB);
for (uint8_t i = 0; i < _nesting; i++)
base::write(ARDUINOJSON_TAB);
}
uint8_t _nesting;
};
template <typename TSource, typename TDestination>
size_t serializeJsonPretty(const TSource &source, TDestination &destination) {
// Produces JsonDocument to create a prettified JSON document.
// https://arduinojson.org/v6/api/json/serializejsonpretty/
template <typename TDestination>
size_t serializeJsonPretty(JsonVariantConst source, TDestination& destination) {
return serialize<PrettyJsonSerializer>(source, destination);
}
template <typename TSource>
size_t serializeJsonPretty(const TSource &source, void *buffer,
size_t bufferSize) {
// Produces JsonDocument to create a prettified JSON document.
// https://arduinojson.org/v6/api/json/serializejsonpretty/
inline size_t serializeJsonPretty(JsonVariantConst source, void* buffer,
size_t bufferSize) {
return serialize<PrettyJsonSerializer>(source, buffer, bufferSize);
}
template <typename TSource>
size_t measureJsonPretty(const TSource &source) {
// Computes the length of the document that serializeJsonPretty() produces.
// https://arduinojson.org/v6/api/json/measurejsonpretty/
inline size_t measureJsonPretty(JsonVariantConst source) {
return measure<PrettyJsonSerializer>(source);
}

View File

@@ -9,7 +9,7 @@
#include <ArduinoJson/Json/EscapeSequence.hpp>
#include <ArduinoJson/Numbers/FloatParts.hpp>
#include <ArduinoJson/Numbers/Integer.hpp>
#include <ArduinoJson/Numbers/JsonInteger.hpp>
#include <ArduinoJson/Polyfills/assert.hpp>
#include <ArduinoJson/Polyfills/attributes.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
@@ -34,17 +34,19 @@ class TextFormatter {
writeRaw("false");
}
void writeString(const char *value) {
void writeString(const char* value) {
ARDUINOJSON_ASSERT(value != NULL);
writeRaw('\"');
while (*value) writeChar(*value++);
while (*value)
writeChar(*value++);
writeRaw('\"');
}
void writeString(const char *value, size_t n) {
void writeString(const char* value, size_t n) {
ARDUINOJSON_ASSERT(value != NULL);
writeRaw('\"');
while (n--) writeChar(*value++);
while (n--)
writeChar(*value++);
writeRaw('\"');
}
@@ -111,8 +113,8 @@ class TextFormatter {
template <typename T>
typename enable_if<is_unsigned<T>::value>::type writeInteger(T value) {
char buffer[22];
char *end = buffer + sizeof(buffer);
char *begin = end;
char* end = buffer + sizeof(buffer);
char* begin = end;
// write the string in reverse order
do {
@@ -127,8 +129,8 @@ class TextFormatter {
void writeDecimals(uint32_t value, int8_t width) {
// buffer should be big enough for all digits and the dot
char buffer[16];
char *end = buffer + sizeof(buffer);
char *begin = end;
char* end = buffer + sizeof(buffer);
char* begin = end;
// write the string in reverse order
while (width--) {
@@ -141,22 +143,22 @@ class TextFormatter {
writeRaw(begin, end);
}
void writeRaw(const char *s) {
_writer.write(reinterpret_cast<const uint8_t *>(s), strlen(s));
void writeRaw(const char* s) {
_writer.write(reinterpret_cast<const uint8_t*>(s), strlen(s));
}
void writeRaw(const char *s, size_t n) {
_writer.write(reinterpret_cast<const uint8_t *>(s), n);
void writeRaw(const char* s, size_t n) {
_writer.write(reinterpret_cast<const uint8_t*>(s), n);
}
void writeRaw(const char *begin, const char *end) {
_writer.write(reinterpret_cast<const uint8_t *>(begin),
void writeRaw(const char* begin, const char* end) {
_writer.write(reinterpret_cast<const uint8_t*>(begin),
static_cast<size_t>(end - begin));
}
template <size_t 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) {
_writer.write(static_cast<uint8_t>(c));
@@ -166,6 +168,6 @@ class TextFormatter {
CountingDecorator<TWriter> _writer;
private:
TextFormatter &operator=(const TextFormatter &); // cannot be assigned
TextFormatter& operator=(const TextFormatter&); // cannot be assigned
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -13,19 +13,19 @@ namespace ARDUINOJSON_NAMESPACE {
#if ARDUINOJSON_ENABLE_ALIGNMENT
inline bool isAligned(size_t value) {
const size_t mask = sizeof(void *) - 1;
const size_t mask = sizeof(void*) - 1;
size_t addr = value;
return (addr & mask) == 0;
}
inline size_t addPadding(size_t bytes) {
const size_t mask = sizeof(void *) - 1;
const size_t mask = sizeof(void*) - 1;
return (bytes + mask) & ~mask;
}
template <size_t bytes>
struct AddPadding {
static const size_t mask = sizeof(void *) - 1;
static const size_t mask = sizeof(void*) - 1;
static const size_t value = (bytes + mask) & ~mask;
};
@@ -47,14 +47,14 @@ struct AddPadding {
#endif
template <typename T>
inline bool isAligned(T *ptr) {
inline bool isAligned(T* ptr) {
return isAligned(reinterpret_cast<size_t>(ptr));
}
template <typename T>
inline T *addPadding(T *p) {
inline T* addPadding(T* p) {
size_t address = addPadding(reinterpret_cast<size_t>(p));
return reinterpret_cast<T *>(address);
return reinterpret_cast<T*>(address);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -14,6 +14,16 @@
#define JSON_STRING_SIZE(SIZE) (SIZE + 1)
// Computes the size required to store an array in a JsonDocument.
// https://arduinojson.org/v6/how-to/determine-the-capacity-of-the-jsondocument/
#define JSON_ARRAY_SIZE(NUMBER_OF_ELEMENTS) \
((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot))
// Returns the size (in bytes) of an object with n elements.
// Can be very handy to determine the size of a StaticMemoryPool.
#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot))
namespace ARDUINOJSON_NAMESPACE {
// _begin _end
@@ -173,7 +183,8 @@ class MemoryPool {
return next;
// jump to next terminator
while (*next) ++next;
while (*next)
++next;
}
return 0;
}
@@ -208,4 +219,35 @@ class MemoryPool {
bool _overflowed;
};
template <typename TAdaptedString, typename TCallback>
bool storeString(MemoryPool* pool, TAdaptedString str,
StringStoragePolicy::Copy, TCallback callback) {
const char* copy = pool->saveString(str);
JsonString storedString(copy, str.size(), JsonString::Copied);
callback(storedString);
return copy != 0;
}
template <typename TAdaptedString, typename TCallback>
bool storeString(MemoryPool*, TAdaptedString str, StringStoragePolicy::Link,
TCallback callback) {
JsonString storedString(str.data(), str.size(), JsonString::Linked);
callback(storedString);
return !str.isNull();
}
template <typename TAdaptedString, typename TCallback>
bool storeString(MemoryPool* pool, TAdaptedString str,
StringStoragePolicy::LinkOrCopy policy, TCallback callback) {
if (policy.link)
return storeString(pool, str, StringStoragePolicy::Link(), callback);
else
return storeString(pool, str, StringStoragePolicy::Copy(), callback);
}
template <typename TAdaptedString, typename TCallback>
bool storeString(MemoryPool* pool, TAdaptedString str, TCallback callback) {
return storeString(pool, str, str.storagePolicy(), callback);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

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

View File

@@ -16,33 +16,31 @@ namespace ARDUINOJSON_NAMESPACE {
template <typename TReader, typename TStringStorage>
class MsgPackDeserializer {
public:
MsgPackDeserializer(MemoryPool &pool, TReader reader,
MsgPackDeserializer(MemoryPool* pool, TReader reader,
TStringStorage stringStorage)
: _pool(&pool),
: _pool(pool),
_reader(reader),
_stringStorage(stringStorage),
_error(DeserializationError::Ok),
_foundSomething(false) {}
template <typename TFilter>
DeserializationError parse(VariantData &variant, TFilter filter,
DeserializationError parse(VariantData& variant, TFilter filter,
NestingLimit nestingLimit) {
parseVariant(&variant, filter, nestingLimit);
return _foundSomething ? _error : DeserializationError::EmptyInput;
DeserializationError::Code err;
err = parseVariant(&variant, filter, nestingLimit);
return _foundSomething ? err : DeserializationError::EmptyInput;
}
private:
bool invalidInput() {
_error = DeserializationError::InvalidInput;
return false;
}
template <typename TFilter>
bool parseVariant(VariantData *variant, TFilter filter,
NestingLimit nestingLimit) {
DeserializationError::Code parseVariant(VariantData* variant, TFilter filter,
NestingLimit nestingLimit) {
DeserializationError::Code err;
uint8_t code = 0; // TODO: why do we need to initialize this variable?
if (!readByte(code))
return false;
err = readByte(code);
if (err)
return err;
_foundSomething = true;
@@ -56,20 +54,20 @@ class MsgPackDeserializer {
switch (code) {
case 0xc0:
// already null
return true;
return DeserializationError::Ok;
case 0xc1:
return invalidInput();
return DeserializationError::InvalidInput;
case 0xc2:
if (allowValue)
variant->setBoolean(false);
return true;
return DeserializationError::Ok;
case 0xc3:
if (allowValue)
variant->setBoolean(true);
return true;
return DeserializationError::Ok;
case 0xc4: // bin 8 (not supported)
return skipString<uint8_t>();
@@ -221,210 +219,260 @@ class MsgPackDeserializer {
if (allowValue)
variant->setInteger(static_cast<int8_t>(code));
return true;
return DeserializationError::Ok;
}
bool readByte(uint8_t &value) {
DeserializationError::Code readByte(uint8_t& value) {
int c = _reader.read();
if (c < 0) {
_error = DeserializationError::IncompleteInput;
return false;
}
if (c < 0)
return DeserializationError::IncompleteInput;
value = static_cast<uint8_t>(c);
return true;
return DeserializationError::Ok;
}
bool readBytes(uint8_t *p, size_t n) {
if (_reader.readBytes(reinterpret_cast<char *>(p), n) == n)
return true;
_error = DeserializationError::IncompleteInput;
return false;
DeserializationError::Code readBytes(uint8_t* p, size_t n) {
if (_reader.readBytes(reinterpret_cast<char*>(p), n) == n)
return DeserializationError::Ok;
return DeserializationError::IncompleteInput;
}
template <typename T>
bool readBytes(T &value) {
return readBytes(reinterpret_cast<uint8_t *>(&value), sizeof(value));
DeserializationError::Code readBytes(T& value) {
return readBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
}
bool skipBytes(size_t n) {
DeserializationError::Code skipBytes(size_t n) {
for (; n; --n) {
if (_reader.read() < 0) {
_error = DeserializationError::IncompleteInput;
return false;
}
if (_reader.read() < 0)
return DeserializationError::IncompleteInput;
}
return true;
return DeserializationError::Ok;
}
template <typename T>
bool readInteger(T &value) {
if (!readBytes(value))
return false;
DeserializationError::Code readInteger(T& value) {
DeserializationError::Code err;
err = readBytes(value);
if (err)
return err;
fixEndianess(value);
return true;
return DeserializationError::Ok;
}
template <typename T>
bool readInteger(VariantData *variant) {
DeserializationError::Code readInteger(VariantData* variant) {
DeserializationError::Code err;
T value;
if (!readInteger(value))
return false;
err = readInteger(value);
if (err)
return err;
variant->setInteger(value);
return true;
return DeserializationError::Ok;
}
template <typename T>
typename enable_if<sizeof(T) == 4, bool>::type readFloat(
VariantData *variant) {
typename enable_if<sizeof(T) == 4, DeserializationError::Code>::type
readFloat(VariantData* variant) {
DeserializationError::Code err;
T value;
if (!readBytes(value))
return false;
err = readBytes(value);
if (err)
return err;
fixEndianess(value);
variant->setFloat(value);
return true;
return DeserializationError::Ok;
}
template <typename T>
typename enable_if<sizeof(T) == 8, bool>::type readDouble(
VariantData *variant) {
typename enable_if<sizeof(T) == 8, DeserializationError::Code>::type
readDouble(VariantData* variant) {
DeserializationError::Code err;
T value;
if (!readBytes(value))
return false;
err = readBytes(value);
if (err)
return err;
fixEndianess(value);
variant->setFloat(value);
return true;
return DeserializationError::Ok;
}
template <typename T>
typename enable_if<sizeof(T) == 4, bool>::type readDouble(
VariantData *variant) {
typename enable_if<sizeof(T) == 4, DeserializationError::Code>::type
readDouble(VariantData* variant) {
DeserializationError::Code err;
uint8_t i[8]; // input is 8 bytes
T value; // output is 4 bytes
uint8_t *o = reinterpret_cast<uint8_t *>(&value);
if (!readBytes(i, 8))
return false;
uint8_t* o = reinterpret_cast<uint8_t*>(&value);
err = readBytes(i, 8);
if (err)
return err;
doubleToFloat(i, o);
fixEndianess(value);
variant->setFloat(value);
return true;
return DeserializationError::Ok;
}
template <typename T>
bool readString(VariantData *variant) {
DeserializationError::Code readString(VariantData* variant) {
DeserializationError::Code err;
T size;
if (!readInteger(size))
return false;
err = readInteger(size);
if (err)
return err;
return readString(variant, size);
}
template <typename T>
bool readString() {
DeserializationError::Code readString() {
DeserializationError::Code err;
T size;
if (!readInteger(size))
return false;
err = readInteger(size);
if (err)
return err;
return readString(size);
}
template <typename T>
bool skipString() {
DeserializationError::Code skipString() {
DeserializationError::Code err;
T size;
if (!readInteger(size))
return false;
err = readInteger(size);
if (err)
return err;
return skipBytes(size);
}
bool readString(VariantData *variant, size_t n) {
if (!readString(n))
return false;
DeserializationError::Code readString(VariantData* variant, size_t n) {
DeserializationError::Code err;
err = readString(n);
if (err)
return err;
variant->setString(_stringStorage.save());
return true;
return DeserializationError::Ok;
}
bool readString(size_t n) {
DeserializationError::Code readString(size_t n) {
DeserializationError::Code err;
_stringStorage.startString();
for (; n; --n) {
uint8_t c;
if (!readBytes(c))
return false;
err = readBytes(c);
if (err)
return err;
_stringStorage.append(static_cast<char>(c));
}
if (!_stringStorage.isValid()) {
_error = DeserializationError::NoMemory;
return false;
}
return true;
if (!_stringStorage.isValid())
return DeserializationError::NoMemory;
return DeserializationError::Ok;
}
template <typename TSize, typename TFilter>
bool readArray(VariantData *variant, TFilter filter,
NestingLimit nestingLimit) {
DeserializationError::Code readArray(VariantData* variant, TFilter filter,
NestingLimit nestingLimit) {
DeserializationError::Code err;
TSize size;
if (!readInteger(size))
return false;
err = readInteger(size);
if (err)
return err;
return readArray(variant, size, filter, nestingLimit);
}
template <typename TFilter>
bool readArray(VariantData *variant, size_t n, TFilter filter,
NestingLimit nestingLimit) {
if (nestingLimit.reached()) {
_error = DeserializationError::TooDeep;
return false;
}
DeserializationError::Code readArray(VariantData* variant, size_t n,
TFilter filter,
NestingLimit nestingLimit) {
DeserializationError::Code err;
if (nestingLimit.reached())
return DeserializationError::TooDeep;
bool allowArray = filter.allowArray();
CollectionData *array = allowArray ? &variant->toArray() : 0;
CollectionData* array = allowArray ? &variant->toArray() : 0;
TFilter memberFilter = filter[0U];
for (; n; --n) {
VariantData *value;
VariantData* value;
if (memberFilter.allow()) {
value = array->addElement(_pool);
if (!value) {
_error = DeserializationError::NoMemory;
return false;
}
if (!value)
return DeserializationError::NoMemory;
} else {
value = 0;
}
if (!parseVariant(value, memberFilter, nestingLimit.decrement()))
return false;
err = parseVariant(value, memberFilter, nestingLimit.decrement());
if (err)
return err;
}
return true;
return DeserializationError::Ok;
}
template <typename TSize, typename TFilter>
bool readObject(VariantData *variant, TFilter filter,
NestingLimit nestingLimit) {
DeserializationError::Code readObject(VariantData* variant, TFilter filter,
NestingLimit nestingLimit) {
DeserializationError::Code err;
TSize size;
if (!readInteger(size))
return false;
err = readInteger(size);
if (err)
return err;
return readObject(variant, size, filter, nestingLimit);
}
template <typename TFilter>
bool readObject(VariantData *variant, size_t n, TFilter filter,
NestingLimit nestingLimit) {
if (nestingLimit.reached()) {
_error = DeserializationError::TooDeep;
return false;
}
DeserializationError::Code readObject(VariantData* variant, size_t n,
TFilter filter,
NestingLimit nestingLimit) {
DeserializationError::Code err;
CollectionData *object = filter.allowObject() ? &variant->toObject() : 0;
if (nestingLimit.reached())
return DeserializationError::TooDeep;
CollectionData* object = filter.allowObject() ? &variant->toObject() : 0;
for (; n; --n) {
if (!readKey())
return false;
err = readKey();
if (err)
return err;
String key = _stringStorage.str();
JsonString key = _stringStorage.str();
TFilter memberFilter = filter[key.c_str()];
VariantData *member;
VariantData* member;
if (memberFilter.allow()) {
ARDUINOJSON_ASSERT(object);
@@ -433,11 +481,9 @@ class MsgPackDeserializer {
// This MUST be done before adding the slot.
key = _stringStorage.save();
VariantSlot *slot = object->addSlot(_pool);
if (!slot) {
_error = DeserializationError::NoMemory;
return false;
}
VariantSlot* slot = object->addSlot(_pool);
if (!slot)
return DeserializationError::NoMemory;
slot->setKey(key);
@@ -446,17 +492,21 @@ class MsgPackDeserializer {
member = 0;
}
if (!parseVariant(member, memberFilter, nestingLimit.decrement()))
return false;
err = parseVariant(member, memberFilter, nestingLimit.decrement());
if (err)
return err;
}
return true;
return DeserializationError::Ok;
}
bool readKey() {
DeserializationError::Code readKey() {
DeserializationError::Code err;
uint8_t code;
if (!readByte(code))
return false;
err = readByte(code);
if (err)
return err;
if ((code & 0xe0) == 0xa0)
return readString(code & 0x1f);
@@ -472,125 +522,136 @@ class MsgPackDeserializer {
return readString<uint32_t>();
default:
return invalidInput();
return DeserializationError::InvalidInput;
}
}
template <typename T>
bool skipExt() {
DeserializationError::Code skipExt() {
DeserializationError::Code err;
T size;
if (!readInteger(size))
return false;
err = readInteger(size);
if (err)
return err;
return skipBytes(size + 1U);
}
MemoryPool *_pool;
MemoryPool* _pool;
TReader _reader;
TStringStorage _stringStorage;
DeserializationError _error;
bool _foundSomething;
};
//
// deserializeMsgPack(JsonDocument&, const std::string&, ...)
//
// ... = NestingLimit
// Parses a MessagePack input and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
template <typename TString>
DeserializationError deserializeMsgPack(
JsonDocument &doc, const TString &input,
JsonDocument& doc, const TString& input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
AllowAllFilter());
}
// ... = Filter, NestingLimit
// Parses a MessagePack input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
template <typename TString>
DeserializationError deserializeMsgPack(
JsonDocument &doc, const TString &input, Filter filter,
JsonDocument& doc, const TString& input, Filter filter,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
}
// ... = NestingLimit, Filter
// Parses a MessagePack input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
template <typename TString>
DeserializationError deserializeMsgPack(JsonDocument &doc, const TString &input,
DeserializationError deserializeMsgPack(JsonDocument& doc, const TString& input,
NestingLimit nestingLimit,
Filter filter) {
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
}
//
// deserializeMsgPack(JsonDocument&, std::istream&, ...)
//
// ... = NestingLimit
// Parses a MessagePack input and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
template <typename TStream>
DeserializationError deserializeMsgPack(
JsonDocument &doc, TStream &input,
JsonDocument& doc, TStream& input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
AllowAllFilter());
}
// ... = Filter, NestingLimit
// Parses a MessagePack input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
template <typename TStream>
DeserializationError deserializeMsgPack(
JsonDocument &doc, TStream &input, Filter filter,
JsonDocument& doc, TStream& input, Filter filter,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
}
// ... = NestingLimit, Filter
// Parses a MessagePack input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
template <typename TStream>
DeserializationError deserializeMsgPack(JsonDocument &doc, TStream &input,
DeserializationError deserializeMsgPack(JsonDocument& doc, TStream& input,
NestingLimit nestingLimit,
Filter filter) {
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
}
//
// deserializeMsgPack(JsonDocument&, char*, ...)
//
// ... = NestingLimit
// Parses a MessagePack input and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
template <typename TChar>
DeserializationError deserializeMsgPack(
JsonDocument &doc, TChar *input,
JsonDocument& doc, TChar* input,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit,
AllowAllFilter());
}
// ... = Filter, NestingLimit
// Parses a MessagePack input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
template <typename TChar>
DeserializationError deserializeMsgPack(
JsonDocument &doc, TChar *input, Filter filter,
JsonDocument& doc, TChar* input, Filter filter,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
}
// ... = NestingLimit, Filter
// Parses a MessagePack input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
template <typename TChar>
DeserializationError deserializeMsgPack(JsonDocument &doc, TChar *input,
DeserializationError deserializeMsgPack(JsonDocument& doc, TChar* input,
NestingLimit nestingLimit,
Filter filter) {
return deserialize<MsgPackDeserializer>(doc, input, nestingLimit, filter);
}
//
// deserializeMsgPack(JsonDocument&, char*, size_t, ...)
//
// ... = NestingLimit
// Parses a MessagePack input and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
template <typename TChar>
DeserializationError deserializeMsgPack(
JsonDocument &doc, TChar *input, size_t inputSize,
JsonDocument& doc, TChar* input, size_t inputSize,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit,
AllowAllFilter());
}
// ... = Filter, NestingLimit
// Parses a MessagePack input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
template <typename TChar>
DeserializationError deserializeMsgPack(
JsonDocument &doc, TChar *input, size_t inputSize, Filter filter,
JsonDocument& doc, TChar* input, size_t inputSize, Filter filter,
NestingLimit nestingLimit = NestingLimit()) {
return deserialize<MsgPackDeserializer>(doc, input, inputSize, nestingLimit,
filter);
}
// ... = NestingLimit, Filter
// Parses a MessagePack input, filters, and puts the result in a JsonDocument.
// https://arduinojson.org/v6/api/msgpack/deserializemsgpack/
template <typename TChar>
DeserializationError deserializeMsgPack(JsonDocument &doc, TChar *input,
DeserializationError deserializeMsgPack(JsonDocument& doc, TChar* input,
size_t inputSize,
NestingLimit nestingLimit,
Filter filter) {

View File

@@ -23,8 +23,8 @@ class MsgPackSerializer : public Visitor<size_t> {
template <typename T>
typename enable_if<sizeof(T) == 4, size_t>::type visitFloat(T value32) {
if (canConvertNumber<Integer>(value32)) {
Integer truncatedValue = Integer(value32);
if (canConvertNumber<JsonInteger>(value32)) {
JsonInteger truncatedValue = JsonInteger(value32);
if (value32 == T(truncatedValue))
return visitSignedInteger(truncatedValue);
}
@@ -55,7 +55,7 @@ class MsgPackSerializer : public Visitor<size_t> {
writeByte(0xDD);
writeInteger(uint32_t(n));
}
for (VariantSlot* slot = array.head(); slot; slot = slot->next()) {
for (const VariantSlot* slot = array.head(); slot; slot = slot->next()) {
slot->data()->accept(*this);
}
return bytesWritten();
@@ -72,7 +72,7 @@ class MsgPackSerializer : public Visitor<size_t> {
writeByte(0xDF);
writeInteger(uint32_t(n));
}
for (VariantSlot* slot = object.head(); slot; slot = slot->next()) {
for (const VariantSlot* slot = object.head(); slot; slot = slot->next()) {
visitString(slot->key());
slot->data()->accept(*this);
}
@@ -107,9 +107,9 @@ class MsgPackSerializer : public Visitor<size_t> {
return bytesWritten();
}
size_t visitSignedInteger(Integer value) {
size_t visitSignedInteger(JsonInteger value) {
if (value > 0) {
visitUnsignedInteger(static_cast<UInt>(value));
visitUnsignedInteger(static_cast<JsonUInt>(value));
} else if (value >= -0x20) {
writeInteger(int8_t(value));
} else if (value >= -0x80) {
@@ -137,7 +137,7 @@ class MsgPackSerializer : public Visitor<size_t> {
return bytesWritten();
}
size_t visitUnsignedInteger(UInt value) {
size_t visitUnsignedInteger(JsonUInt value) {
if (value <= 0x7F) {
writeInteger(uint8_t(value));
} else if (value <= 0xFF) {
@@ -197,19 +197,23 @@ class MsgPackSerializer : public Visitor<size_t> {
CountingDecorator<TWriter> _writer;
};
template <typename TSource, typename TDestination>
inline size_t serializeMsgPack(const TSource& source, TDestination& output) {
// Produces a MessagePack document.
// https://arduinojson.org/v6/api/msgpack/serializemsgpack/
template <typename TDestination>
inline size_t serializeMsgPack(JsonVariantConst source, TDestination& output) {
return serialize<MsgPackSerializer>(source, output);
}
template <typename TSource>
inline size_t serializeMsgPack(const TSource& source, void* output,
// Produces a MessagePack document.
// https://arduinojson.org/v6/api/msgpack/serializemsgpack/
inline size_t serializeMsgPack(JsonVariantConst source, void* output,
size_t size) {
return serialize<MsgPackSerializer>(source, output, size);
}
template <typename TSource>
inline size_t measureMsgPack(const TSource& source) {
// Computes the length of the document that serializeMsgPack() produces.
// https://arduinojson.org/v6/api/msgpack/measuremsgpack/
inline size_t measureMsgPack(JsonVariantConst source) {
return measure<MsgPackSerializer>(source);
}

View File

@@ -9,38 +9,38 @@
namespace ARDUINOJSON_NAMESPACE {
#if ARDUINOJSON_LITTLE_ENDIAN
inline void swapBytes(uint8_t &a, uint8_t &b) {
inline void swapBytes(uint8_t& a, uint8_t& b) {
uint8_t t(a);
a = b;
b = t;
}
inline void fixEndianess(uint8_t *p, integral_constant<size_t, 8>) {
inline void fixEndianess(uint8_t* p, integral_constant<size_t, 8>) {
swapBytes(p[0], p[7]);
swapBytes(p[1], p[6]);
swapBytes(p[2], p[5]);
swapBytes(p[3], p[4]);
}
inline void fixEndianess(uint8_t *p, integral_constant<size_t, 4>) {
inline void fixEndianess(uint8_t* p, integral_constant<size_t, 4>) {
swapBytes(p[0], p[3]);
swapBytes(p[1], p[2]);
}
inline void fixEndianess(uint8_t *p, integral_constant<size_t, 2>) {
inline void fixEndianess(uint8_t* p, integral_constant<size_t, 2>) {
swapBytes(p[0], p[1]);
}
inline void fixEndianess(uint8_t *, integral_constant<size_t, 1>) {}
inline void fixEndianess(uint8_t*, integral_constant<size_t, 1>) {}
template <typename T>
inline void fixEndianess(T &value) {
fixEndianess(reinterpret_cast<uint8_t *>(&value),
inline void fixEndianess(T& value) {
fixEndianess(reinterpret_cast<uint8_t*>(&value),
integral_constant<size_t, sizeof(T)>());
}
#else
template <typename T>
inline void fixEndianess(T &) {}
inline void fixEndianess(T&) {}
#endif
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -12,6 +12,7 @@
#include <ArduinoJson/Polyfills/math.hpp>
#include <ArduinoJson/Polyfills/preprocessor.hpp>
#include <ArduinoJson/Polyfills/static_array.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
namespace ARDUINOJSON_NAMESPACE {
@@ -116,6 +117,22 @@ struct FloatTraits<T, 8 /*64bits*/> {
return forge(0x7FEFFFFF, 0xFFFFFFFF);
}
template <typename TOut> // int64_t
static T highest_for(
typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value &&
sizeof(TOut) == 8,
signed>::type* = 0) {
return forge(0x43DFFFFF, 0xFFFFFFFF); // 9.2233720368547748e+18
}
template <typename TOut> // uint64_t
static T highest_for(
typename enable_if<is_integral<TOut>::value && is_unsigned<TOut>::value &&
sizeof(TOut) == 8,
unsigned>::type* = 0) {
return forge(0x43EFFFFF, 0xFFFFFFFF); // 1.8446744073709549568e+19
}
static T lowest() {
return forge(0xFFEFFFFF, 0xFFFFFFFF);
}
@@ -212,6 +229,38 @@ struct FloatTraits<T, 4 /*32bits*/> {
return forge(0x7f7fffff);
}
template <typename TOut> // int32_t
static T highest_for(
typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value &&
sizeof(TOut) == 4,
signed>::type* = 0) {
return forge(0x4EFFFFFF); // 2.14748352E9
}
template <typename TOut> // uint32_t
static T highest_for(
typename enable_if<is_integral<TOut>::value && is_unsigned<TOut>::value &&
sizeof(TOut) == 4,
unsigned>::type* = 0) {
return forge(0x4F7FFFFF); // 4.29496704E9
}
template <typename TOut> // int64_t
static T highest_for(
typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value &&
sizeof(TOut) == 8,
signed>::type* = 0) {
return forge(0x5EFFFFFF); // 9.22337148709896192E18
}
template <typename TOut> // uint64_t
static T highest_for(
typename enable_if<is_integral<TOut>::value && is_unsigned<TOut>::value &&
sizeof(TOut) == 8,
unsigned>::type* = 0) {
return forge(0x5F7FFFFF); // 1.844674297419792384E19
}
static T lowest() {
return forge(0xFf7fffff);
}

View File

@@ -10,8 +10,8 @@
namespace ARDUINOJSON_NAMESPACE {
#if ARDUINOJSON_USE_DOUBLE
typedef double Float;
typedef double JsonFloat;
#else
typedef float Float;
typedef float JsonFloat;
#endif
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -12,18 +12,18 @@
namespace ARDUINOJSON_NAMESPACE {
#if ARDUINOJSON_USE_LONG_LONG
typedef int64_t Integer;
typedef uint64_t UInt;
typedef int64_t JsonInteger;
typedef uint64_t JsonUInt;
#else
typedef long Integer;
typedef unsigned long UInt;
typedef long JsonInteger;
typedef unsigned long JsonUInt;
#endif
} // namespace ARDUINOJSON_NAMESPACE
#if ARDUINOJSON_HAS_LONG_LONG && !ARDUINOJSON_USE_LONG_LONG
# define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T) \
static_assert(sizeof(T) <= sizeof(ARDUINOJSON_NAMESPACE::Integer), \
static_assert(sizeof(T) <= sizeof(ARDUINOJSON_NAMESPACE::JsonInteger), \
"To use 64-bit integers with ArduinoJson, you must set " \
"ARDUINOJSON_USE_LONG_LONG to 1. See " \
"https://arduinojson.org/v6/api/config/use_long_long/");

View File

@@ -4,7 +4,7 @@
#pragma once
#include <ArduinoJson/Numbers/Integer.hpp>
#include <ArduinoJson/Numbers/JsonInteger.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
namespace ARDUINOJSON_NAMESPACE {
@@ -20,7 +20,7 @@ enum CompareResult {
};
template <typename T>
CompareResult arithmeticCompare(const T &lhs, const T &rhs) {
CompareResult arithmeticCompare(const T& lhs, const T& rhs) {
if (lhs < rhs)
return COMPARE_RESULT_LESS;
else if (lhs > rhs)
@@ -31,38 +31,38 @@ CompareResult arithmeticCompare(const T &lhs, const T &rhs) {
template <typename T1, typename T2>
CompareResult arithmeticCompare(
const T1 &lhs, const T2 &rhs,
const T1& lhs, const T2& rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
sizeof(T1) < sizeof(T2),
int // Using int instead of void to avoid C2572 on
// Visual Studio 2012, 2013, and 2015
>::type * = 0) {
>::type* = 0) {
return arithmeticCompare<T2>(static_cast<T2>(lhs), rhs);
}
template <typename T1, typename T2>
CompareResult arithmeticCompare(
const T1 &lhs, const T2 &rhs,
const T1& lhs, const T2& rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
sizeof(T2) < sizeof(T1)>::type * = 0) {
sizeof(T2) < sizeof(T1)>::type* = 0) {
return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
}
template <typename T1, typename T2>
CompareResult arithmeticCompare(
const T1 &lhs, const T2 &rhs,
const T1& lhs, const T2& rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
is_signed<T1>::value == is_signed<T2>::value &&
sizeof(T2) == sizeof(T1)>::type * = 0) {
sizeof(T2) == sizeof(T1)>::type* = 0) {
return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
}
template <typename T1, typename T2>
CompareResult arithmeticCompare(
const T1 &lhs, const T2 &rhs,
const T1& lhs, const T2& rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
is_unsigned<T1>::value && is_signed<T2>::value &&
sizeof(T2) == sizeof(T1)>::type * = 0) {
sizeof(T2) == sizeof(T1)>::type* = 0) {
if (rhs < 0)
return COMPARE_RESULT_GREATER;
return arithmeticCompare<T1>(lhs, static_cast<T1>(rhs));
@@ -70,10 +70,10 @@ CompareResult arithmeticCompare(
template <typename T1, typename T2>
CompareResult arithmeticCompare(
const T1 &lhs, const T2 &rhs,
const T1& lhs, const T2& rhs,
typename enable_if<is_integral<T1>::value && is_integral<T2>::value &&
is_signed<T1>::value && is_unsigned<T2>::value &&
sizeof(T2) == sizeof(T1)>::type * = 0) {
sizeof(T2) == sizeof(T1)>::type* = 0) {
if (lhs < 0)
return COMPARE_RESULT_LESS;
return arithmeticCompare<T2>(static_cast<T2>(lhs), rhs);
@@ -81,23 +81,24 @@ CompareResult arithmeticCompare(
template <typename T1, typename T2>
CompareResult arithmeticCompare(
const T1 &lhs, const T2 &rhs,
const T1& lhs, const T2& rhs,
typename enable_if<is_floating_point<T1>::value ||
is_floating_point<T2>::value>::type * = 0) {
is_floating_point<T2>::value>::type* = 0) {
return arithmeticCompare<double>(static_cast<double>(lhs),
static_cast<double>(rhs));
}
template <typename T2>
CompareResult arithmeticCompareNegateLeft(
UInt, const T2 &, typename enable_if<is_unsigned<T2>::value>::type * = 0) {
JsonUInt, const T2&,
typename enable_if<is_unsigned<T2>::value>::type* = 0) {
return COMPARE_RESULT_LESS;
}
template <typename T2>
CompareResult arithmeticCompareNegateLeft(
UInt lhs, const T2 &rhs,
typename enable_if<is_signed<T2>::value>::type * = 0) {
JsonUInt lhs, const T2& rhs,
typename enable_if<is_signed<T2>::value>::type* = 0) {
if (rhs > 0)
return COMPARE_RESULT_LESS;
return arithmeticCompare(-rhs, static_cast<T2>(lhs));
@@ -105,14 +106,15 @@ CompareResult arithmeticCompareNegateLeft(
template <typename T1>
CompareResult arithmeticCompareNegateRight(
const T1 &, UInt, typename enable_if<is_unsigned<T1>::value>::type * = 0) {
const T1&, JsonUInt,
typename enable_if<is_unsigned<T1>::value>::type* = 0) {
return COMPARE_RESULT_GREATER;
}
template <typename T1>
CompareResult arithmeticCompareNegateRight(
const T1 &lhs, UInt rhs,
typename enable_if<is_signed<T1>::value>::type * = 0) {
const T1& lhs, JsonUInt rhs,
typename enable_if<is_signed<T1>::value>::type* = 0) {
if (lhs > 0)
return COMPARE_RESULT_GREATER;
return arithmeticCompare(static_cast<T1>(rhs), -lhs);

View File

@@ -14,7 +14,8 @@
# pragma GCC diagnostic ignored "-Wconversion"
#endif
#include <ArduinoJson/Numbers/Float.hpp>
#include <ArduinoJson/Numbers/FloatTraits.hpp>
#include <ArduinoJson/Numbers/JsonFloat.hpp>
#include <ArduinoJson/Polyfills/limits.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
@@ -95,17 +96,34 @@ canConvertNumber(TIn value) {
return value <= TIn(numeric_limits<TOut>::highest());
}
// float -> int32
// float -> int64
// float32 -> int16
// float64 -> int32
template <typename TOut, typename TIn>
typename enable_if<is_floating_point<TIn>::value &&
!is_floating_point<TOut>::value,
typename enable_if<is_floating_point<TIn>::value && is_integral<TOut>::value &&
sizeof(TOut) < sizeof(TIn),
bool>::type
canConvertNumber(TIn value) {
return value >= numeric_limits<TOut>::lowest() &&
value <= numeric_limits<TOut>::highest();
}
// float32 -> int32
// float32 -> uint32
// float32 -> int64
// float32 -> uint64
// float64 -> int64
// float64 -> uint64
template <typename TOut, typename TIn>
typename enable_if<is_floating_point<TIn>::value && is_integral<TOut>::value &&
sizeof(TOut) >= sizeof(TIn),
bool>::type
canConvertNumber(TIn value) {
// Avoid error "9.22337e+18 is outside the range of representable values of
// type 'long'"
return value >= numeric_limits<TOut>::lowest() &&
value <= FloatTraits<TIn>::template highest_for<TOut>();
}
template <typename TOut, typename TIn>
TOut convertNumber(TIn value) {
return canConvertNumber<TOut>(value) ? TOut(value) : 0;

View File

@@ -19,8 +19,8 @@ template <typename A, typename B>
struct choose_largest : conditional<(sizeof(A) > sizeof(B)), A, B> {};
inline bool parseNumber(const char* s, VariantData& result) {
typedef FloatTraits<Float> traits;
typedef choose_largest<traits::mantissa_type, UInt>::type mantissa_t;
typedef FloatTraits<JsonFloat> traits;
typedef choose_largest<traits::mantissa_type, JsonUInt>::type mantissa_t;
typedef traits::exponent_type exponent_t;
ARDUINOJSON_ASSERT(s != 0);
@@ -55,7 +55,7 @@ inline bool parseNumber(const char* s, VariantData& result) {
mantissa_t mantissa = 0;
exponent_t exponent_offset = 0;
const mantissa_t maxUint = UInt(-1);
const mantissa_t maxUint = JsonUInt(-1);
while (isdigit(*s)) {
uint8_t digit = uint8_t(*s - '0');
@@ -71,13 +71,13 @@ inline bool parseNumber(const char* s, VariantData& result) {
if (*s == '\0') {
if (is_negative) {
const mantissa_t sintMantissaMax = mantissa_t(1)
<< (sizeof(Integer) * 8 - 1);
<< (sizeof(JsonInteger) * 8 - 1);
if (mantissa <= sintMantissaMax) {
result.setInteger(Integer(~mantissa + 1));
result.setInteger(JsonInteger(~mantissa + 1));
return true;
}
} else {
result.setInteger(UInt(mantissa));
result.setInteger(JsonUInt(mantissa));
return true;
}
}
@@ -136,8 +136,8 @@ inline bool parseNumber(const char* s, VariantData& result) {
if (*s != '\0')
return false;
Float final_result =
traits::make_float(static_cast<Float>(mantissa), exponent);
JsonFloat final_result =
traits::make_float(static_cast<JsonFloat>(mantissa), exponent);
result.setFloat(is_negative ? -final_result : final_result);
return true;
@@ -148,6 +148,6 @@ inline T parseNumber(const char* s) {
VariantData value;
value.init(); // VariantData is a POD, so it has no constructor
parseNumber(s, value);
return Converter<T>::fromJson(VariantConstRef(&value));
return Converter<T>::fromJson(JsonVariantConst(&value));
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,246 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Object/JsonObjectConst.hpp>
#include <ArduinoJson/Object/MemberProxy.hpp>
namespace ARDUINOJSON_NAMESPACE {
class JsonArray;
// A reference to an object in a JsonDocument.
// https://arduinojson.org/v6/api/jsonobject/
class JsonObject : public VariantOperators<JsonObject> {
friend class VariantAttorney;
public:
typedef JsonObjectIterator iterator;
// Creates an unbound reference.
FORCE_INLINE JsonObject() : _data(0), _pool(0) {}
// INTERNAL USE ONLY
FORCE_INLINE JsonObject(MemoryPool* buf, CollectionData* data)
: _data(data), _pool(buf) {}
operator JsonVariant() const {
void* data = _data; // prevent warning cast-align
return JsonVariant(_pool, reinterpret_cast<VariantData*>(data));
}
operator JsonObjectConst() const {
return JsonObjectConst(_data);
}
operator JsonVariantConst() const {
return JsonVariantConst(collectionToVariant(_data));
}
// Returns true if the reference is unbound.
// https://arduinojson.org/v6/api/jsonobject/isnull/
FORCE_INLINE bool isNull() const {
return _data == 0;
}
// Returns true if the reference is bound.
// https://arduinojson.org/v6/api/jsonobject/isnull/
FORCE_INLINE operator bool() const {
return _data != 0;
}
// Returns the number of bytes occupied by the object.
// https://arduinojson.org/v6/api/jsonobject/memoryusage/
FORCE_INLINE size_t memoryUsage() const {
return _data ? _data->memoryUsage() : 0;
}
// Returns the depth (nesting level) of the object.
// https://arduinojson.org/v6/api/jsonobject/nesting/
FORCE_INLINE size_t nesting() const {
return variantNesting(collectionToVariant(_data));
}
// Returns the number of members in the object.
// https://arduinojson.org/v6/api/jsonobject/size/
FORCE_INLINE size_t size() const {
return _data ? _data->size() : 0;
}
// Returns an iterator to the first key-value pair of the object.
// https://arduinojson.org/v6/api/jsonobject/begin/
FORCE_INLINE iterator begin() const {
if (!_data)
return iterator();
return iterator(_pool, _data->head());
}
// Returns an iterator following the last key-value pair of the object.
// https://arduinojson.org/v6/api/jsonobject/end/
FORCE_INLINE iterator end() const {
return iterator();
}
// Removes all the members of the object.
// ⚠️ Doesn't release the memory associated with the removed members.
// https://arduinojson.org/v6/api/jsonobject/clear/
void clear() const {
if (!_data)
return;
_data->clear();
}
// Copies an object.
// https://arduinojson.org/v6/api/jsonobject/set/
FORCE_INLINE bool set(JsonObjectConst src) {
if (!_data || !src._data)
return false;
return _data->copyFrom(*src._data, _pool);
}
// Compares the content of two objects.
FORCE_INLINE bool operator==(JsonObject rhs) const {
return JsonObjectConst(_data) == JsonObjectConst(rhs._data);
}
// Gets or sets the member with specified key.
// https://arduinojson.org/v6/api/jsonobject/subscript/
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value,
MemberProxy<JsonObject, TString> >::type
operator[](const TString& key) const {
return MemberProxy<JsonObject, TString>(*this, key);
}
// Gets or sets the member with specified key.
// https://arduinojson.org/v6/api/jsonobject/subscript/
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value,
MemberProxy<JsonObject, TChar*> >::type
operator[](TChar* key) const {
return MemberProxy<JsonObject, TChar*>(*this, key);
}
// Removes the member at the specified iterator.
// ⚠️ Doesn't release the memory associated with the removed member.
// https://arduinojson.org/v6/api/jsonobject/remove/
FORCE_INLINE void remove(iterator it) const {
if (!_data)
return;
_data->removeSlot(it._slot);
}
// Removes the member with the specified key.
// ⚠️ Doesn't release the memory associated with the removed member.
// https://arduinojson.org/v6/api/jsonobject/remove/
template <typename TString>
FORCE_INLINE void remove(const TString& key) const {
removeMember(adaptString(key));
}
// Removes the member with the specified key.
// ⚠️ Doesn't release the memory associated with the removed member.
// https://arduinojson.org/v6/api/jsonobject/remove/
template <typename TChar>
FORCE_INLINE void remove(TChar* key) const {
removeMember(adaptString(key));
}
// Returns true if the object contains the specified key.
// https://arduinojson.org/v6/api/jsonobject/containskey/
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value, bool>::type
containsKey(const TString& key) const {
return getMember(adaptString(key)) != 0;
}
// Returns true if the object contains the specified key.
// https://arduinojson.org/v6/api/jsonobject/containskey/
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value, bool>::type
containsKey(TChar* key) const {
return getMember(adaptString(key)) != 0;
}
// Creates an array and adds it to the object.
// https://arduinojson.org/v6/api/jsonobject/createnestedarray/
template <typename TString>
FORCE_INLINE JsonArray createNestedArray(const TString& key) const;
// Creates an array and adds it to the object.
// https://arduinojson.org/v6/api/jsonobject/createnestedarray/
template <typename TChar>
FORCE_INLINE JsonArray createNestedArray(TChar* key) const;
// Creates an object and adds it to the object.
// https://arduinojson.org/v6/api/jsonobject/createnestedobject/
template <typename TString>
JsonObject createNestedObject(const TString& key) const {
return operator[](key).template to<JsonObject>();
}
// Creates an object and adds it to the object.
// https://arduinojson.org/v6/api/jsonobject/createnestedobject/
template <typename TChar>
JsonObject createNestedObject(TChar* key) const {
return operator[](key).template to<JsonObject>();
}
private:
MemoryPool* getPool() const {
return _pool;
}
VariantData* getData() const {
return collectionToVariant(_data);
}
VariantData* getOrCreateData() const {
return collectionToVariant(_data);
}
template <typename TAdaptedString>
inline VariantData* getMember(TAdaptedString key) const {
if (!_data)
return 0;
return _data->getMember(key);
}
template <typename TAdaptedString>
void removeMember(TAdaptedString key) const {
if (!_data)
return;
_data->removeMember(key);
}
CollectionData* _data;
MemoryPool* _pool;
};
template <>
struct Converter<JsonObject> : private VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) {
variantCopyFrom(getData(dst), getData(src), getPool(dst));
}
static JsonObject fromJson(JsonVariant src) {
VariantData* data = getData(src);
MemoryPool* pool = getPool(src);
return JsonObject(pool, data != 0 ? data->asObject() : 0);
}
static InvalidConversion<JsonVariantConst, JsonObject> fromJson(
JsonVariantConst);
static bool checkJson(JsonVariantConst) {
return false;
}
static bool checkJson(JsonVariant src) {
VariantData* data = getData(src);
return data && data->isObject();
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,156 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Object/JsonObjectIterator.hpp>
#include <ArduinoJson/Variant/VariantOperators.hpp>
namespace ARDUINOJSON_NAMESPACE {
// A read-only reference to an object in a JsonDocument.
// https://arduinojson.org/v6/api/jsonobjectconst/
class JsonObjectConst : public VariantOperators<JsonObjectConst> {
friend class JsonObject;
friend class VariantAttorney;
public:
typedef JsonObjectConstIterator iterator;
// Creates an unbound reference.
JsonObjectConst() : _data(0) {}
// INTERNAL USE ONLY
JsonObjectConst(const CollectionData* data) : _data(data) {}
operator JsonVariantConst() const {
return JsonVariantConst(collectionToVariant(_data));
}
// Returns true if the reference is unbound.
// https://arduinojson.org/v6/api/jsonobjectconst/isnull/
FORCE_INLINE bool isNull() const {
return _data == 0;
}
// Returns true if the reference is bound.
// https://arduinojson.org/v6/api/jsonobjectconst/isnull/
FORCE_INLINE operator bool() const {
return _data != 0;
}
// Returns the number of bytes occupied by the object.
// https://arduinojson.org/v6/api/jsonobjectconst/memoryusage/
FORCE_INLINE size_t memoryUsage() const {
return _data ? _data->memoryUsage() : 0;
}
// Returns the depth (nesting level) of the object.
// https://arduinojson.org/v6/api/jsonobjectconst/nesting/
FORCE_INLINE size_t nesting() const {
return variantNesting(collectionToVariant(_data));
}
// Returns the number of members in the object.
// https://arduinojson.org/v6/api/jsonobjectconst/size/
FORCE_INLINE size_t size() const {
return _data ? _data->size() : 0;
}
// Returns an iterator to the first key-value pair of the object.
// https://arduinojson.org/v6/api/jsonobjectconst/begin/
FORCE_INLINE iterator begin() const {
if (!_data)
return iterator();
return iterator(_data->head());
}
// Returns an iterator following the last key-value pair of the object.
// https://arduinojson.org/v6/api/jsonobjectconst/end/
FORCE_INLINE iterator end() const {
return iterator();
}
// Returns true if the object contains the specified key.
// https://arduinojson.org/v6/api/jsonobjectconst/containskey/
template <typename TString>
FORCE_INLINE bool containsKey(const TString& key) const {
return getMember(adaptString(key)) != 0;
}
// Returns true if the object contains the specified key.
// https://arduinojson.org/v6/api/jsonobjectconst/containskey/
template <typename TChar>
FORCE_INLINE bool containsKey(TChar* key) const {
return getMember(adaptString(key)) != 0;
}
// Gets the member with specified key.
// https://arduinojson.org/v6/api/jsonobjectconst/subscript/
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value, JsonVariantConst>::type
operator[](const TString& key) const {
return JsonVariantConst(getMember(adaptString(key)));
}
// Gets the member with specified key.
// https://arduinojson.org/v6/api/jsonobjectconst/subscript/
template <typename TChar>
FORCE_INLINE
typename enable_if<IsString<TChar*>::value, JsonVariantConst>::type
operator[](TChar* key) const {
return JsonVariantConst(getMember(adaptString(key)));
}
// Compares objects.
FORCE_INLINE bool operator==(JsonObjectConst rhs) const {
if (_data == rhs._data)
return true;
if (!_data || !rhs._data)
return false;
size_t count = 0;
for (iterator it = begin(); it != end(); ++it) {
if (it->value() != rhs[it->key()])
return false;
count++;
}
return count == rhs.size();
}
private:
const VariantData* getData() const {
return collectionToVariant(_data);
}
template <typename TAdaptedString>
const VariantData* getMember(TAdaptedString key) const {
if (!_data)
return 0;
return _data->getMember(key);
}
const CollectionData* _data;
};
template <>
struct Converter<JsonObjectConst> : private VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) {
variantCopyFrom(getData(dst), getData(src), getPool(dst));
}
static JsonObjectConst fromJson(JsonVariantConst src) {
const VariantData* data = getData(src);
return data != 0 ? data->asObject() : 0;
}
static bool checkJson(JsonVariantConst src) {
const VariantData* data = getData(src);
return data && data->isObject();
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,81 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Array/JsonArray.hpp>
#include <ArduinoJson/Object/JsonObject.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename TString>
inline JsonArray JsonObject::createNestedArray(const TString& key) const {
return operator[](key).template to<JsonArray>();
}
template <typename TChar>
inline JsonArray JsonObject::createNestedArray(TChar* key) const {
return operator[](key).template to<JsonArray>();
}
template <typename TDerived>
template <typename TString>
inline JsonArray VariantRefBase<TDerived>::createNestedArray(
const TString& key) const {
return operator[](key).template to<JsonArray>();
}
template <typename TDerived>
template <typename TChar>
inline JsonArray VariantRefBase<TDerived>::createNestedArray(TChar* key) const {
return operator[](key).template to<JsonArray>();
}
template <typename TDerived>
template <typename TString>
inline JsonObject VariantRefBase<TDerived>::createNestedObject(
const TString& key) const {
return operator[](key).template to<JsonObject>();
}
template <typename TDerived>
template <typename TChar>
inline JsonObject VariantRefBase<TDerived>::createNestedObject(
TChar* key) const {
return operator[](key).template to<JsonObject>();
}
template <typename TDerived>
template <typename TString>
inline typename enable_if<IsString<TString>::value, bool>::type
VariantRefBase<TDerived>::containsKey(const TString& key) const {
return variantGetMember(VariantAttorney::getData(derived()),
adaptString(key)) != 0;
}
template <typename TDerived>
template <typename TChar>
inline typename enable_if<IsString<TChar*>::value, bool>::type
VariantRefBase<TDerived>::containsKey(TChar* key) const {
return variantGetMember(VariantAttorney::getData(derived()),
adaptString(key)) != 0;
}
template <typename TDerived>
template <typename TString>
inline typename enable_if<IsString<TString*>::value,
MemberProxy<TDerived, TString*> >::type
VariantRefBase<TDerived>::operator[](TString* key) const {
return MemberProxy<TDerived, TString*>(derived(), key);
}
template <typename TDerived>
template <typename TString>
inline typename enable_if<IsString<TString>::value,
MemberProxy<TDerived, TString> >::type
VariantRefBase<TDerived>::operator[](const TString& key) const {
return MemberProxy<TDerived, TString>(derived(), key);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,119 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Object/JsonPair.hpp>
#include <ArduinoJson/Variant/SlotFunctions.hpp>
namespace ARDUINOJSON_NAMESPACE {
class JsonPairPtr {
public:
JsonPairPtr(MemoryPool* pool, VariantSlot* slot) : _pair(pool, slot) {}
const JsonPair* operator->() const {
return &_pair;
}
const JsonPair& operator*() const {
return _pair;
}
private:
JsonPair _pair;
};
class JsonObjectIterator {
friend class JsonObject;
public:
JsonObjectIterator() : _slot(0) {}
explicit JsonObjectIterator(MemoryPool* pool, VariantSlot* slot)
: _pool(pool), _slot(slot) {}
JsonPair operator*() const {
return JsonPair(_pool, _slot);
}
JsonPairPtr operator->() {
return JsonPairPtr(_pool, _slot);
}
bool operator==(const JsonObjectIterator& other) const {
return _slot == other._slot;
}
bool operator!=(const JsonObjectIterator& other) const {
return _slot != other._slot;
}
JsonObjectIterator& operator++() {
_slot = _slot->next();
return *this;
}
JsonObjectIterator& operator+=(size_t distance) {
_slot = _slot->next(distance);
return *this;
}
private:
MemoryPool* _pool;
VariantSlot* _slot;
};
class JsonPairConstPtr {
public:
JsonPairConstPtr(const VariantSlot* slot) : _pair(slot) {}
const JsonPairConst* operator->() const {
return &_pair;
}
const JsonPairConst& operator*() const {
return _pair;
}
private:
JsonPairConst _pair;
};
class JsonObjectConstIterator {
friend class JsonObject;
public:
JsonObjectConstIterator() : _slot(0) {}
explicit JsonObjectConstIterator(const VariantSlot* slot) : _slot(slot) {}
JsonPairConst operator*() const {
return JsonPairConst(_slot);
}
JsonPairConstPtr operator->() {
return JsonPairConstPtr(_slot);
}
bool operator==(const JsonObjectConstIterator& other) const {
return _slot == other._slot;
}
bool operator!=(const JsonObjectConstIterator& other) const {
return _slot != other._slot;
}
JsonObjectConstIterator& operator++() {
_slot = _slot->next();
return *this;
}
JsonObjectConstIterator& operator+=(size_t distance) {
_slot = _slot->next(distance);
return *this;
}
private:
const VariantSlot* _slot;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,67 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Strings/JsonString.hpp>
#include <ArduinoJson/Variant/JsonVariant.hpp>
#include <ArduinoJson/Variant/JsonVariantConst.hpp>
namespace ARDUINOJSON_NAMESPACE {
// A key-value pair.
// https://arduinojson.org/v6/api/jsonobject/begin_end/
class JsonPair {
public:
// INTERNAL USE ONLY
JsonPair(MemoryPool* pool, VariantSlot* slot) {
if (slot) {
_key = JsonString(slot->key(), slot->ownsKey() ? JsonString::Copied
: JsonString::Linked);
_value = JsonVariant(pool, slot->data());
}
}
// Returns the key.
JsonString key() const {
return _key;
}
// Returns the value.
JsonVariant value() const {
return _value;
}
private:
JsonString _key;
JsonVariant _value;
};
// A read-only key-value pair.
// https://arduinojson.org/v6/api/jsonobjectconst/begin_end/
class JsonPairConst {
public:
JsonPairConst(const VariantSlot* slot) {
if (slot) {
_key = JsonString(slot->key(), slot->ownsKey() ? JsonString::Copied
: JsonString::Linked);
_value = JsonVariantConst(slot->data());
}
}
// Returns the key.
JsonString key() const {
return _key;
}
// Returns the value.
JsonVariantConst value() const {
return _value;
}
private:
JsonString _key;
JsonVariantConst _value;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -4,203 +4,61 @@
#pragma once
#include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Variant/VariantOperators.hpp>
#include <ArduinoJson/Variant/VariantRef.hpp>
#include <ArduinoJson/Variant/VariantShortcuts.hpp>
#include <ArduinoJson/Variant/VariantTo.hpp>
#ifdef _MSC_VER
# pragma warning(push)
# pragma warning(disable : 4522)
#endif
#include <ArduinoJson/Variant/VariantRefBase.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename TObject, typename TStringRef>
class MemberProxy : public VariantOperators<MemberProxy<TObject, TStringRef> >,
public VariantShortcuts<MemberProxy<TObject, TStringRef> >,
public Visitable,
public VariantTag {
typedef MemberProxy<TObject, TStringRef> this_type;
// A proxy class to get or set a member of an object.
// https://arduinojson.org/v6/api/jsonobject/subscript/
template <typename TUpstream, typename TStringRef>
class MemberProxy
: public VariantRefBase<MemberProxy<TUpstream, TStringRef> >,
public VariantOperators<MemberProxy<TUpstream, TStringRef> > {
friend class VariantAttorney;
public:
typedef VariantRef variant_type;
FORCE_INLINE MemberProxy(TUpstream upstream, TStringRef key)
: _upstream(upstream), _key(key) {}
FORCE_INLINE MemberProxy(TObject variant, TStringRef key)
: _object(variant), _key(key) {}
MemberProxy(const MemberProxy& src)
: _upstream(src._upstream), _key(src._key) {}
FORCE_INLINE MemberProxy(const MemberProxy &src)
: _object(src._object), _key(src._key) {}
FORCE_INLINE operator VariantConstRef() const {
return getUpstreamMember();
}
FORCE_INLINE this_type &operator=(const this_type &src) {
getOrAddUpstreamMember().set(src);
FORCE_INLINE MemberProxy& operator=(const MemberProxy& src) {
this->set(src);
return *this;
}
template <typename TValue>
FORCE_INLINE typename enable_if<!is_array<TValue>::value, this_type &>::type
operator=(const TValue &src) {
getOrAddUpstreamMember().set(src);
template <typename T>
FORCE_INLINE MemberProxy& operator=(const T& src) {
this->set(src);
return *this;
}
// operator=(char*)
// operator=(const char*)
// operator=(const __FlashStringHelper*)
template <typename TChar>
FORCE_INLINE this_type &operator=(TChar *src) {
getOrAddUpstreamMember().set(src);
template <typename T>
FORCE_INLINE MemberProxy& operator=(T* src) {
this->set(src);
return *this;
}
FORCE_INLINE void clear() const {
getUpstreamMember().clear();
}
FORCE_INLINE bool isNull() const {
return getUpstreamMember().isNull();
}
template <typename T>
FORCE_INLINE typename enable_if<!is_same<T, char *>::value, T>::type as()
const {
return getUpstreamMember().template as<T>();
}
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, char *>::value, const char *>::type
ARDUINOJSON_DEPRECATED("Replace as<char*>() with as<const char*>()")
as() const {
return as<const char *>();
}
template <typename T>
FORCE_INLINE operator T() const {
return getUpstreamMember();
}
template <typename TValue>
FORCE_INLINE bool is() const {
return getUpstreamMember().template is<TValue>();
}
FORCE_INLINE size_t size() const {
return getUpstreamMember().size();
}
FORCE_INLINE size_t memoryUsage() const {
return getUpstreamMember().memoryUsage();
}
FORCE_INLINE void remove(size_t index) const {
getUpstreamMember().remove(index);
}
// remove(char*) const
// remove(const char*) const
// remove(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar *>::value>::type remove(
TChar *key) const {
getUpstreamMember().remove(key);
}
// remove(const std::string&) const
// remove(const String&) const
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
const TString &key) const {
getUpstreamMember().remove(key);
}
template <typename TValue>
FORCE_INLINE typename VariantTo<TValue>::type to() {
return getOrAddUpstreamMember().template to<TValue>();
}
template <typename TValue>
FORCE_INLINE bool set(const TValue &value) {
return getOrAddUpstreamMember().set(value);
}
// set(char*) const
// set(const char*) const
// set(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE bool set(TChar *value) {
return getOrAddUpstreamMember().set(value);
}
template <typename TVisitor>
typename TVisitor::result_type accept(TVisitor &visitor) const {
return getUpstreamMember().accept(visitor);
}
FORCE_INLINE VariantRef addElement() const {
return getOrAddUpstreamMember().addElement();
}
FORCE_INLINE VariantRef getElement(size_t index) const {
return getUpstreamMember().getElement(index);
}
FORCE_INLINE VariantRef getOrAddElement(size_t index) const {
return getOrAddUpstreamMember().getOrAddElement(index);
}
// getMember(char*) const
// getMember(const char*) const
// getMember(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef getMember(TChar *key) const {
return getUpstreamMember().getMember(key);
}
// getMember(const std::string&) const
// getMember(const String&) const
template <typename TString>
FORCE_INLINE VariantRef getMember(const TString &key) const {
return getUpstreamMember().getMember(key);
}
// getOrAddMember(char*) const
// getOrAddMember(const char*) const
// getOrAddMember(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef getOrAddMember(TChar *key) const {
return getOrAddUpstreamMember().getOrAddMember(key);
}
// getOrAddMember(const std::string&) const
// getOrAddMember(const String&) const
template <typename TString>
FORCE_INLINE VariantRef getOrAddMember(const TString &key) const {
return getOrAddUpstreamMember().getOrAddMember(key);
}
private:
FORCE_INLINE VariantRef getUpstreamMember() const {
return _object.getMember(_key);
FORCE_INLINE MemoryPool* getPool() const {
return VariantAttorney::getPool(_upstream);
}
FORCE_INLINE VariantRef getOrAddUpstreamMember() const {
return _object.getOrAddMember(_key);
FORCE_INLINE VariantData* getData() const {
return variantGetMember(VariantAttorney::getData(_upstream),
adaptString(_key));
}
friend void convertToJson(const this_type &src, VariantRef dst) {
dst.set(src.getUpstreamMember());
FORCE_INLINE VariantData* getOrCreateData() const {
return variantGetOrAddMember(VariantAttorney::getOrCreateData(_upstream),
adaptString(_key),
VariantAttorney::getPool(_upstream));
}
TObject _object;
private:
TUpstream _upstream;
TStringRef _key;
};
} // namespace ARDUINOJSON_NAMESPACE
#ifdef _MSC_VER
# pragma warning(pop)
#endif

View File

@@ -1,52 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Collection/CollectionData.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename TVisitor>
typename TVisitor::result_type objectAccept(const CollectionData *obj,
TVisitor &visitor) {
if (obj)
return visitor.visitObject(*obj);
else
return visitor.visitNull();
}
inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) {
if (lhs == rhs)
return true;
if (!lhs || !rhs)
return false;
return lhs->equalsObject(*rhs);
}
template <typename TAdaptedString>
inline VariantData *objectGetMember(const CollectionData *obj,
TAdaptedString key) {
if (!obj)
return 0;
return obj->getMember(key);
}
template <typename TAdaptedString>
void objectRemove(CollectionData *obj, TAdaptedString key) {
if (!obj)
return;
obj->removeMember(key);
}
template <typename TAdaptedString, typename TStoragePolicy>
inline VariantData *objectGetOrAddMember(CollectionData *obj,
TAdaptedString key, MemoryPool *pool,
TStoragePolicy storage_policy) {
if (!obj)
return 0;
return obj->getOrAddMember(key, pool, storage_policy);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,69 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Array/ArrayRef.hpp>
#include <ArduinoJson/Object/ObjectRef.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename TObject>
template <typename TString>
inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(
const TString& key) const {
return impl()->getOrAddMember(key).template to<ArrayRef>();
}
template <typename TObject>
template <typename TChar>
inline ArrayRef ObjectShortcuts<TObject>::createNestedArray(TChar* key) const {
return impl()->getOrAddMember(key).template to<ArrayRef>();
}
template <typename TObject>
template <typename TString>
inline ObjectRef ObjectShortcuts<TObject>::createNestedObject(
const TString& key) const {
return impl()->getOrAddMember(key).template to<ObjectRef>();
}
template <typename TObject>
template <typename TChar>
inline ObjectRef ObjectShortcuts<TObject>::createNestedObject(
TChar* key) const {
return impl()->getOrAddMember(key).template to<ObjectRef>();
}
template <typename TObject>
template <typename TString>
inline typename enable_if<IsString<TString>::value, bool>::type
ObjectShortcuts<TObject>::containsKey(const TString& key) const {
return !impl()->getMember(key).isUnbound();
}
template <typename TObject>
template <typename TChar>
inline typename enable_if<IsString<TChar*>::value, bool>::type
ObjectShortcuts<TObject>::containsKey(TChar* key) const {
return !impl()->getMember(key).isUnbound();
}
template <typename TObject>
template <typename TString>
inline typename enable_if<IsString<TString*>::value,
MemberProxy<TObject, TString*> >::type
ObjectShortcuts<TObject>::operator[](TString* key) const {
return MemberProxy<TObject, TString*>(*impl(), key);
}
template <typename TObject>
template <typename TString>
inline typename enable_if<IsString<TString>::value,
MemberProxy<TObject, TString> >::type
ObjectShortcuts<TObject>::operator[](const TString& key) const {
return MemberProxy<TObject, TString>(*impl(), key);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,123 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Object/Pair.hpp>
#include <ArduinoJson/Variant/SlotFunctions.hpp>
namespace ARDUINOJSON_NAMESPACE {
class PairPtr {
public:
PairPtr(MemoryPool *pool, VariantSlot *slot) : _pair(pool, slot) {}
const Pair *operator->() const {
return &_pair;
}
const Pair &operator*() const {
return _pair;
}
private:
Pair _pair;
};
class ObjectIterator {
public:
ObjectIterator() : _slot(0) {}
explicit ObjectIterator(MemoryPool *pool, VariantSlot *slot)
: _pool(pool), _slot(slot) {}
Pair operator*() const {
return Pair(_pool, _slot);
}
PairPtr operator->() {
return PairPtr(_pool, _slot);
}
bool operator==(const ObjectIterator &other) const {
return _slot == other._slot;
}
bool operator!=(const ObjectIterator &other) const {
return _slot != other._slot;
}
ObjectIterator &operator++() {
_slot = _slot->next();
return *this;
}
ObjectIterator &operator+=(size_t distance) {
_slot = _slot->next(distance);
return *this;
}
VariantSlot *internal() {
return _slot;
}
private:
MemoryPool *_pool;
VariantSlot *_slot;
};
class PairConstPtr {
public:
PairConstPtr(const VariantSlot *slot) : _pair(slot) {}
const PairConst *operator->() const {
return &_pair;
}
const PairConst &operator*() const {
return _pair;
}
private:
PairConst _pair;
};
class ObjectConstIterator {
public:
ObjectConstIterator() : _slot(0) {}
explicit ObjectConstIterator(const VariantSlot *slot) : _slot(slot) {}
PairConst operator*() const {
return PairConst(_slot);
}
PairConstPtr operator->() {
return PairConstPtr(_slot);
}
bool operator==(const ObjectConstIterator &other) const {
return _slot == other._slot;
}
bool operator!=(const ObjectConstIterator &other) const {
return _slot != other._slot;
}
ObjectConstIterator &operator++() {
_slot = _slot->next();
return *this;
}
ObjectConstIterator &operator+=(size_t distance) {
_slot = _slot->next(distance);
return *this;
}
const VariantSlot *internal() {
return _slot;
}
private:
const VariantSlot *_slot;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,282 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Object/ObjectFunctions.hpp>
#include <ArduinoJson/Object/ObjectIterator.hpp>
// Returns the size (in bytes) of an object with n elements.
// Can be very handy to determine the size of a StaticMemoryPool.
#define JSON_OBJECT_SIZE(NUMBER_OF_ELEMENTS) \
((NUMBER_OF_ELEMENTS) * sizeof(ARDUINOJSON_NAMESPACE::VariantSlot))
namespace ARDUINOJSON_NAMESPACE {
template <typename TData>
class ObjectRefBase {
public:
operator VariantConstRef() const {
const void* data = _data; // prevent warning cast-align
return VariantConstRef(reinterpret_cast<const VariantData*>(data));
}
template <typename TVisitor>
typename TVisitor::result_type accept(TVisitor& visitor) const {
return objectAccept(_data, visitor);
}
FORCE_INLINE bool isNull() const {
return _data == 0;
}
FORCE_INLINE operator bool() const {
return _data != 0;
}
FORCE_INLINE size_t memoryUsage() const {
return _data ? _data->memoryUsage() : 0;
}
FORCE_INLINE size_t nesting() const {
return _data ? _data->nesting() : 0;
}
FORCE_INLINE size_t size() const {
return _data ? _data->size() : 0;
}
protected:
ObjectRefBase(TData* data) : _data(data) {}
TData* _data;
};
class ObjectConstRef : public ObjectRefBase<const CollectionData>,
public Visitable {
friend class ObjectRef;
typedef ObjectRefBase<const CollectionData> base_type;
public:
typedef ObjectConstIterator iterator;
ObjectConstRef() : base_type(0) {}
ObjectConstRef(const CollectionData* data) : base_type(data) {}
FORCE_INLINE iterator begin() const {
if (!_data)
return iterator();
return iterator(_data->head());
}
FORCE_INLINE iterator end() const {
return iterator();
}
// containsKey(const std::string&) const
// containsKey(const String&) const
template <typename TString>
FORCE_INLINE bool containsKey(const TString& key) const {
return !getMember(key).isUnbound();
}
// containsKey(char*) const
// containsKey(const char*) const
// containsKey(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE bool containsKey(TChar* key) const {
return !getMember(key).isUnbound();
}
// getMember(const std::string&) const
// getMember(const String&) const
template <typename TString>
FORCE_INLINE VariantConstRef getMember(const TString& key) const {
return get_impl(adaptString(key));
}
// getMember(char*) const
// getMember(const char*) const
// getMember(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantConstRef getMember(TChar* key) const {
return get_impl(adaptString(key));
}
// operator[](const std::string&) const
// operator[](const String&) const
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value, VariantConstRef>::type
operator[](const TString& key) const {
return get_impl(adaptString(key));
}
// operator[](char*) const
// operator[](const char*) const
// operator[](const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE
typename enable_if<IsString<TChar*>::value, VariantConstRef>::type
operator[](TChar* key) const {
return get_impl(adaptString(key));
}
FORCE_INLINE bool operator==(ObjectConstRef rhs) const {
return objectEquals(_data, rhs._data);
}
private:
template <typename TAdaptedString>
FORCE_INLINE VariantConstRef get_impl(TAdaptedString key) const {
return VariantConstRef(objectGetMember(_data, key));
}
};
class ObjectRef : public ObjectRefBase<CollectionData>,
public ObjectShortcuts<ObjectRef>,
public Visitable {
typedef ObjectRefBase<CollectionData> base_type;
public:
typedef ObjectIterator iterator;
FORCE_INLINE ObjectRef() : base_type(0), _pool(0) {}
FORCE_INLINE ObjectRef(MemoryPool* buf, CollectionData* data)
: base_type(data), _pool(buf) {}
operator VariantRef() const {
void* data = _data; // prevent warning cast-align
return VariantRef(_pool, reinterpret_cast<VariantData*>(data));
}
operator ObjectConstRef() const {
return ObjectConstRef(_data);
}
FORCE_INLINE iterator begin() const {
if (!_data)
return iterator();
return iterator(_pool, _data->head());
}
FORCE_INLINE iterator end() const {
return iterator();
}
void clear() const {
if (!_data)
return;
_data->clear();
}
FORCE_INLINE bool set(ObjectConstRef src) {
if (!_data || !src._data)
return false;
return _data->copyFrom(*src._data, _pool);
}
// getMember(const std::string&) const
// getMember(const String&) const
template <typename TString>
FORCE_INLINE VariantRef getMember(const TString& key) const {
return VariantRef(_pool, objectGetMember(_data, adaptString(key)));
}
// getMember(char*) const
// getMember(const char*) const
// getMember(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef getMember(TChar* key) const {
return VariantRef(_pool, objectGetMember(_data, adaptString(key)));
}
// getOrAddMember(const std::string&) const
// getOrAddMember(const String&) const
template <typename TString>
FORCE_INLINE VariantRef getOrAddMember(const TString& key) const {
return VariantRef(_pool,
objectGetOrAddMember(_data, adaptString(key), _pool,
getStringStoragePolicy(key)));
}
// getOrAddMember(char*) const
// getOrAddMember(const char*) const
// getOrAddMember(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef getOrAddMember(TChar* key) const {
return VariantRef(_pool,
objectGetOrAddMember(_data, adaptString(key), _pool,
getStringStoragePolicy(key)));
}
FORCE_INLINE bool operator==(ObjectRef rhs) const {
return objectEquals(_data, rhs._data);
}
FORCE_INLINE void remove(iterator it) const {
if (!_data)
return;
_data->removeSlot(it.internal());
}
// remove(const std::string&) const
// remove(const String&) const
template <typename TString>
FORCE_INLINE void remove(const TString& key) const {
objectRemove(_data, adaptString(key));
}
// remove(char*) const
// remove(const char*) const
// remove(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE void remove(TChar* key) const {
objectRemove(_data, adaptString(key));
}
private:
MemoryPool* _pool;
};
template <>
struct Converter<ObjectConstRef> {
static void toJson(VariantConstRef src, VariantRef dst) {
variantCopyFrom(getData(dst), getData(src), getPool(dst));
}
static ObjectConstRef fromJson(VariantConstRef src) {
return ObjectConstRef(variantAsObject(getData(src)));
}
static bool checkJson(VariantConstRef src) {
const VariantData* data = getData(src);
return data && data->isObject();
}
};
template <>
struct Converter<ObjectRef> {
static void toJson(VariantConstRef src, VariantRef dst) {
variantCopyFrom(getData(dst), getData(src), getPool(dst));
}
static ObjectRef fromJson(VariantRef src) {
VariantData* data = getData(src);
MemoryPool* pool = getPool(src);
return ObjectRef(pool, data != 0 ? data->asObject() : 0);
}
static InvalidConversion<VariantConstRef, ObjectRef> fromJson(
VariantConstRef);
static bool checkJson(VariantConstRef) {
return false;
}
static bool checkJson(VariantRef src) {
VariantData* data = getData(src);
return data && data->isObject();
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,73 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Polyfills/attributes.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Strings/StringAdapters.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename TParent, typename TStringRef>
class MemberProxy;
template <typename TObject>
class ObjectShortcuts {
public:
// containsKey(const std::string&) const
// containsKey(const String&) const
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value, bool>::type
containsKey(const TString &key) const;
// containsKey(char*) const
// containsKey(const char*) const
// containsKey(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar *>::value, bool>::type
containsKey(TChar *key) const;
// operator[](const std::string&) const
// operator[](const String&) const
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value,
MemberProxy<TObject, TString> >::type
operator[](const TString &key) const;
// operator[](char*) const
// operator[](const char*) const
// operator[](const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar *>::value,
MemberProxy<TObject, TChar *> >::type
operator[](TChar *key) const;
// createNestedArray(const std::string&) const
// createNestedArray(const String&) const
template <typename TString>
FORCE_INLINE ArrayRef createNestedArray(const TString &key) const;
// createNestedArray(char*) const
// createNestedArray(const char*) const
// createNestedArray(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE ArrayRef createNestedArray(TChar *key) const;
// createNestedObject(const std::string&) const
// createNestedObject(const String&) const
template <typename TString>
ObjectRef createNestedObject(const TString &key) const;
// createNestedObject(char*) const
// createNestedObject(const char*) const
// createNestedObject(const __FlashStringHelper*) const
template <typename TChar>
ObjectRef createNestedObject(TChar *key) const;
private:
const TObject *impl() const {
return static_cast<const TObject *>(this);
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,57 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Strings/String.hpp>
#include <ArduinoJson/Variant/VariantRef.hpp>
namespace ARDUINOJSON_NAMESPACE {
// A key value pair for CollectionData.
class Pair {
public:
Pair(MemoryPool* pool, VariantSlot* slot) {
if (slot) {
_key = String(slot->key(),
slot->ownsKey() ? String::Copied : String::Linked);
_value = VariantRef(pool, slot->data());
}
}
String key() const {
return _key;
}
VariantRef value() const {
return _value;
}
private:
String _key;
VariantRef _value;
};
class PairConst {
public:
PairConst(const VariantSlot* slot) {
if (slot) {
_key = String(slot->key(),
slot->ownsKey() ? String::Copied : String::Linked);
_value = VariantConstRef(slot->data());
}
}
String key() const {
return _key;
}
VariantConstRef value() const {
return _value;
}
private:
String _key;
VariantConstRef _value;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -9,32 +9,16 @@
# define FORCE_INLINE // __forceinline causes C4714 when returning std::string
# define NO_INLINE __declspec(noinline)
# ifndef ARDUINOJSON_DEPRECATED
# define ARDUINOJSON_DEPRECATED(msg) __declspec(deprecated(msg))
# endif
#elif defined(__GNUC__) // GCC or Clang
# define FORCE_INLINE __attribute__((always_inline))
# define NO_INLINE __attribute__((noinline))
# ifndef ARDUINOJSON_DEPRECATED
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
# define ARDUINOJSON_DEPRECATED(msg) __attribute__((deprecated(msg)))
# else
# define ARDUINOJSON_DEPRECATED(msg) __attribute__((deprecated))
# endif
# endif
#else // Other compilers
# define FORCE_INLINE
# define NO_INLINE
# ifndef ARDUINOJSON_DEPRECATED
# define ARDUINOJSON_DEPRECATED(msg)
# endif
#endif
#if __cplusplus >= 201103L

View File

@@ -23,7 +23,8 @@ struct pgm_p {
inline size_t strlen_P(ARDUINOJSON_NAMESPACE::pgm_p s) {
const char* p = s.address;
ARDUINOJSON_ASSERT(p != NULL);
while (pgm_read_byte(p)) p++;
while (pgm_read_byte(p))
p++;
return size_t(p - s.address);
}
#endif

View File

@@ -13,14 +13,11 @@ namespace ARDUINOJSON_NAMESPACE {
template <typename TBase, typename TDerived>
class is_base_of {
protected: // <- to avoid GCC's "all member functions in class are private"
typedef char Yes[1];
typedef char No[2];
static Yes &probe(const TBase *);
static No &probe(...);
static int probe(const TBase*);
static char probe(...);
public:
static const bool value =
sizeof(probe(reinterpret_cast<TDerived *>(0))) == sizeof(Yes);
sizeof(probe(reinterpret_cast<TDerived*>(0))) == sizeof(int);
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -11,16 +11,13 @@ namespace ARDUINOJSON_NAMESPACE {
template <typename T>
struct is_class {
protected: // <- to avoid GCC's "all member functions in class are private"
typedef char Yes[1];
typedef char No[2];
template <typename U>
static Yes &probe(void (U::*)(void));
static int probe(void (U::*)(void));
template <typename>
static No &probe(...);
static char probe(...);
public:
static const bool value = sizeof(probe<T>(0)) == sizeof(Yes);
static const bool value = sizeof(probe<T>(0)) == sizeof(int);
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -24,14 +24,13 @@ namespace ARDUINOJSON_NAMESPACE {
template <typename From, typename To>
struct is_convertible {
protected: // <- to avoid GCC's "all member functions in class are private"
typedef char Yes[1];
typedef char No[2];
static int probe(To);
static char probe(...);
static Yes &probe(To);
static No &probe(...);
static From& _from;
public:
static const bool value = sizeof(probe(declval<From>())) == sizeof(Yes);
static const bool value = sizeof(probe(_from)) == sizeof(int);
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -13,7 +13,7 @@ class Writer< ::String, void> {
static const size_t bufferCapacity = ARDUINOJSON_STRING_BUFFER_SIZE;
public:
explicit Writer(::String &str) : _destination(&str) {
explicit Writer(::String& str) : _destination(&str) {
_size = 0;
}
@@ -29,7 +29,7 @@ class Writer< ::String, void> {
return 1;
}
size_t write(const uint8_t *s, size_t n) {
size_t write(const uint8_t* s, size_t n) {
for (size_t i = 0; i < n; i++) {
write(s[i]);
}
@@ -45,7 +45,7 @@ class Writer< ::String, void> {
}
private:
::String *_destination;
::String* _destination;
char _buffer[bufferCapacity];
size_t _size;
};

View File

@@ -10,7 +10,7 @@ namespace ARDUINOJSON_NAMESPACE {
class StaticStringWriter {
public:
StaticStringWriter(char *buf, size_t size) : end(buf + size), p(buf) {}
StaticStringWriter(char* buf, size_t size) : end(buf + size), p(buf) {}
size_t write(uint8_t c) {
if (p >= end)
@@ -19,8 +19,8 @@ class StaticStringWriter {
return 1;
}
size_t write(const uint8_t *s, size_t n) {
char *begin = p;
size_t write(const uint8_t* s, size_t n) {
char* begin = p;
while (p < end && n > 0) {
*p++ = static_cast<char>(*s++);
n--;
@@ -29,7 +29,7 @@ class StaticStringWriter {
}
private:
char *end;
char *p;
char* end;
char* p;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -22,19 +22,19 @@ template <typename TDestination>
class Writer<TDestination,
typename enable_if<is_std_string<TDestination>::value>::type> {
public:
Writer(TDestination &str) : _str(&str) {}
Writer(TDestination& str) : _str(&str) {}
size_t write(uint8_t c) {
_str->operator+=(static_cast<char>(c));
return 1;
}
size_t write(const uint8_t *s, size_t n) {
_str->append(reinterpret_cast<const char *>(s), n);
size_t write(const uint8_t* s, size_t n) {
_str->append(reinterpret_cast<const char*>(s), n);
return n;
}
private:
TDestination *_str;
TDestination* _str;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -5,14 +5,15 @@
#pragma once
#include <ArduinoJson/Serialization/Writers/DummyWriter.hpp>
#include <ArduinoJson/Variant/VariantFunctions.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <template <typename> class TSerializer, typename TSource>
size_t measure(const TSource &source) {
template <template <typename> class TSerializer>
size_t measure(JsonVariantConst source) {
DummyWriter dp;
TSerializer<DummyWriter> serializer(dp);
return source.accept(serializer);
return variantAccept(VariantAttorney::getData(source), serializer);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -5,49 +5,43 @@
#pragma once
#include <ArduinoJson/Serialization/Writer.hpp>
#include <ArduinoJson/Variant/VariantFunctions.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <template <typename> class TSerializer, typename TSource,
typename TWriter>
size_t doSerialize(const TSource &source, TWriter writer) {
template <template <typename> class TSerializer, typename TWriter>
size_t doSerialize(JsonVariantConst source, TWriter writer) {
TSerializer<TWriter> serializer(writer);
return source.accept(serializer);
return variantAccept(VariantAttorney::getData(source), serializer);
}
template <template <typename> class TSerializer, typename TSource,
typename TDestination>
size_t serialize(const TSource &source, TDestination &destination) {
template <template <typename> class TSerializer, typename TDestination>
size_t serialize(JsonVariantConst source, TDestination& destination) {
Writer<TDestination> writer(destination);
return doSerialize<TSerializer>(source, writer);
}
template <template <typename> class TSerializer, typename TSource>
template <template <typename> class TSerializer>
typename enable_if<!TSerializer<StaticStringWriter>::producesText, size_t>::type
serialize(const TSource &source, void *buffer, size_t bufferSize) {
StaticStringWriter writer(reinterpret_cast<char *>(buffer), bufferSize);
serialize(JsonVariantConst source, void* buffer, size_t bufferSize) {
StaticStringWriter writer(reinterpret_cast<char*>(buffer), bufferSize);
return doSerialize<TSerializer>(source, writer);
}
template <template <typename> class TSerializer, typename TSource>
template <template <typename> class TSerializer>
typename enable_if<TSerializer<StaticStringWriter>::producesText, size_t>::type
serialize(const TSource &source, void *buffer, size_t bufferSize) {
StaticStringWriter writer(reinterpret_cast<char *>(buffer), bufferSize);
serialize(JsonVariantConst source, void* buffer, size_t bufferSize) {
StaticStringWriter writer(reinterpret_cast<char*>(buffer), bufferSize);
size_t n = doSerialize<TSerializer>(source, writer);
// add null-terminator for text output (not counted in the size)
if (n < bufferSize)
reinterpret_cast<char *>(buffer)[n] = 0;
reinterpret_cast<char*>(buffer)[n] = 0;
return n;
}
template <template <typename> class TSerializer, typename TSource,
typename TChar, size_t N>
#if defined _MSC_VER && _MSC_VER < 1900
typename enable_if<sizeof(remove_reference<TChar>::type) == 1, size_t>::type
#else
typename enable_if<sizeof(TChar) == 1, size_t>::type
#endif
serialize(const TSource &source, TChar (&buffer)[N]) {
template <template <typename> class TSerializer, typename TChar, size_t N>
typename enable_if<IsChar<TChar>::value, size_t>::type serialize(
JsonVariantConst source, TChar (&buffer)[N]) {
return serialize<TSerializer>(source, buffer, N);
}

View File

@@ -10,7 +10,7 @@ namespace ARDUINOJSON_NAMESPACE {
class StringCopier {
public:
StringCopier(MemoryPool& pool) : _pool(&pool) {}
StringCopier(MemoryPool* pool) : _pool(pool) {}
void startString() {
_pool->getFreeZone(&_ptr, &_capacity);
@@ -19,18 +19,21 @@ class StringCopier {
_pool->markAsOverflowed();
}
String save() {
JsonString save() {
ARDUINOJSON_ASSERT(_ptr);
ARDUINOJSON_ASSERT(_size < _capacity); // needs room for the terminator
return String(_pool->saveStringFromFreeZone(_size), _size, String::Copied);
return JsonString(_pool->saveStringFromFreeZone(_size), _size,
JsonString::Copied);
}
void append(const char* s) {
while (*s) append(*s++);
while (*s)
append(*s++);
}
void append(const char* s, size_t n) {
while (n-- > 0) append(*s++);
while (n-- > 0)
append(*s++);
}
void append(char c) {
@@ -48,11 +51,11 @@ class StringCopier {
return _size;
}
String str() const {
JsonString str() const {
ARDUINOJSON_ASSERT(_ptr);
ARDUINOJSON_ASSERT(_size < _capacity);
_ptr[_size] = 0;
return String(_ptr, _size, String::Copied);
return JsonString(_ptr, _size, JsonString::Copied);
}
private:

View File

@@ -5,7 +5,7 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
#include <ArduinoJson/Strings/String.hpp>
#include <ArduinoJson/Strings/JsonString.hpp>
namespace ARDUINOJSON_NAMESPACE {
@@ -17,8 +17,8 @@ class StringMover {
_startPtr = _writePtr;
}
FORCE_INLINE String save() {
String s = str();
FORCE_INLINE JsonString save() {
JsonString s = str();
_writePtr++;
return s;
}
@@ -31,9 +31,9 @@ class StringMover {
return true;
}
String str() const {
JsonString str() const {
_writePtr[0] = 0; // terminator
return String(_startPtr, size(), String::Linked);
return JsonString(_startPtr, size(), JsonString::Linked);
}
size_t size() const {

View File

@@ -10,13 +10,14 @@
namespace ARDUINOJSON_NAMESPACE {
template <typename TInput>
StringCopier makeStringStorage(TInput&, MemoryPool& pool) {
StringCopier makeStringStorage(TInput&, MemoryPool* pool) {
ARDUINOJSON_ASSERT(pool != 0);
return StringCopier(pool);
}
template <typename TChar>
StringMover makeStringStorage(
TChar* input, MemoryPool&,
TChar* input, MemoryPool*,
typename enable_if<!is_const<TChar>::value>::type* = 0) {
return StringMover(reinterpret_cast<char*>(input));
}

View File

@@ -7,18 +7,19 @@
#include <Arduino.h>
#include <ArduinoJson/Strings/Adapters/RamString.hpp>
#include <ArduinoJson/Strings/IsString.hpp>
#include <ArduinoJson/Strings/StringAdapter.hpp>
namespace ARDUINOJSON_NAMESPACE {
inline SizedRamString adaptString(const ::String& s) {
return SizedRamString(s.c_str(), s.length());
}
template <typename T>
struct StringAdapter<
T, typename enable_if<is_same<T, ::String>::value ||
is_same<T, ::StringSumHelper>::value>::type> {
typedef SizedRamString AdaptedString;
template <>
struct IsString< ::String> : true_type {};
template <>
struct IsString< ::StringSumHelper> : true_type {};
static AdaptedString adapt(const ::String& s) {
return AdaptedString(s.c_str(), s.length());
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -7,7 +7,7 @@
#include <Arduino.h>
#include <ArduinoJson/Polyfills/pgmspace.hpp>
#include <ArduinoJson/Strings/IsString.hpp>
#include <ArduinoJson/Strings/StringAdapter.hpp>
namespace ARDUINOJSON_NAMESPACE {
@@ -61,20 +61,31 @@ class FlashString {
::memcpy_P(p, s._str, n);
}
StringStoragePolicy::Copy storagePolicy() const {
return StringStoragePolicy::Copy();
}
private:
const char* _str;
size_t _size;
};
inline FlashString adaptString(const __FlashStringHelper* s) {
return FlashString(s, s ? strlen_P(reinterpret_cast<const char*>(s)) : 0);
}
template <>
struct StringAdapter<const __FlashStringHelper*, void> {
typedef FlashString AdaptedString;
inline FlashString adaptString(const __FlashStringHelper* s, size_t n) {
return FlashString(s, n);
}
static AdaptedString adapt(const __FlashStringHelper* s) {
return AdaptedString(s, s ? strlen_P(reinterpret_cast<const char*>(s)) : 0);
}
};
template <>
struct IsString<const __FlashStringHelper*> : true_type {};
struct SizedStringAdapter<const __FlashStringHelper*, void> {
typedef FlashString AdaptedString;
static AdaptedString adapt(const __FlashStringHelper* s, size_t n) {
return AdaptedString(s, n);
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -5,16 +5,32 @@
#pragma once
#include <ArduinoJson/Strings/Adapters/RamString.hpp>
#include <ArduinoJson/Strings/IsString.hpp>
#include <ArduinoJson/Strings/String.hpp>
#include <ArduinoJson/Strings/JsonString.hpp>
#include <ArduinoJson/Strings/StringAdapter.hpp>
namespace ARDUINOJSON_NAMESPACE {
inline SizedRamString adaptString(const String& s) {
return SizedRamString(s.c_str(), s.size());
}
class JsonStringAdapter : public SizedRamString {
public:
JsonStringAdapter(const JsonString& s)
: SizedRamString(s.c_str(), s.size()), _linked(s.isLinked()) {}
StringStoragePolicy::LinkOrCopy storagePolicy() const {
StringStoragePolicy::LinkOrCopy policy = {_linked};
return policy;
}
private:
bool _linked;
};
template <>
struct IsString<String> : true_type {};
struct StringAdapter<JsonString> {
typedef JsonStringAdapter AdaptedString;
static AdaptedString adapt(const JsonString& s) {
return AdaptedString(s);
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -8,10 +8,15 @@
#include <string.h> // strcmp
#include <ArduinoJson/Polyfills/assert.hpp>
#include <ArduinoJson/Strings/IsString.hpp>
#include <ArduinoJson/Strings/StoragePolicy.hpp>
#include <ArduinoJson/Strings/StringAdapter.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename T>
struct IsChar
: integral_constant<bool, is_integral<T>::value && sizeof(T) == 1> {};
class ZeroTerminatedRamString {
public:
static const size_t typeSortKey = 3;
@@ -48,30 +53,49 @@ class ZeroTerminatedRamString {
return stringCompare(a, b) == 0;
}
StringStoragePolicy::Copy storagePolicy() const {
return StringStoragePolicy::Copy();
}
protected:
const char* _str;
};
template <>
struct IsString<char*> : true_type {};
template <typename TChar>
struct StringAdapter<TChar*, typename enable_if<IsChar<TChar>::value>::type> {
typedef ZeroTerminatedRamString AdaptedString;
inline ZeroTerminatedRamString adaptString(const char* s) {
return ZeroTerminatedRamString(s);
}
static AdaptedString adapt(const TChar* p) {
return AdaptedString(reinterpret_cast<const char*>(p));
}
};
template <typename TChar, size_t N>
struct StringAdapter<TChar[N], typename enable_if<IsChar<TChar>::value>::type> {
typedef ZeroTerminatedRamString AdaptedString;
static AdaptedString adapt(const TChar* p) {
return AdaptedString(reinterpret_cast<const char*>(p));
}
};
class StaticStringAdapter : public ZeroTerminatedRamString {
public:
StaticStringAdapter(const char* str) : ZeroTerminatedRamString(str) {}
StringStoragePolicy::Link storagePolicy() const {
return StringStoragePolicy::Link();
}
};
template <>
struct IsString<unsigned char*> : true_type {};
struct StringAdapter<const char*, void> {
typedef StaticStringAdapter AdaptedString;
inline ZeroTerminatedRamString adaptString(const unsigned char* s) {
return adaptString(reinterpret_cast<const char*>(s));
}
template <>
struct IsString<signed char*> : true_type {};
inline ZeroTerminatedRamString adaptString(const signed char* s) {
return adaptString(reinterpret_cast<const char*>(s));
}
static AdaptedString adapt(const char* p) {
return AdaptedString(p);
}
};
class SizedRamString {
public:
@@ -97,23 +121,23 @@ class SizedRamString {
return _str;
}
StringStoragePolicy::Copy storagePolicy() const {
return StringStoragePolicy::Copy();
}
protected:
const char* _str;
size_t _size;
};
inline SizedRamString adaptString(const char* s, size_t n) {
return SizedRamString(s, n);
}
template <typename TChar>
struct SizedStringAdapter<TChar*,
typename enable_if<IsChar<TChar>::value>::type> {
typedef SizedRamString AdaptedString;
template <size_t N>
struct IsString<char[N]> : true_type {};
static AdaptedString adapt(const TChar* p, size_t n) {
return AdaptedString(reinterpret_cast<const char*>(p), n);
}
};
template <size_t N>
struct IsString<const char[N]> : true_type {};
template <size_t N>
inline SizedRamString adaptString(char s[N]) {
return SizedRamString(s, strlen(s));
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -11,13 +11,13 @@
namespace ARDUINOJSON_NAMESPACE {
template <typename TCharTraits, typename TAllocator>
inline SizedRamString adaptString(
const std::basic_string<char, TCharTraits, TAllocator>& s) {
return SizedRamString(s.c_str(), s.size());
}
struct StringAdapter<std::basic_string<char, TCharTraits, TAllocator>, void> {
typedef SizedRamString AdaptedString;
template <typename TCharTraits, typename TAllocator>
struct IsString<std::basic_string<char, TCharTraits, TAllocator> > : true_type {
static AdaptedString adapt(
const std::basic_string<char, TCharTraits, TAllocator>& s) {
return AdaptedString(s.c_str(), s.size());
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -10,11 +10,13 @@
namespace ARDUINOJSON_NAMESPACE {
inline SizedRamString adaptString(const std::string_view& s) {
return SizedRamString(s.data(), s.size());
}
template <>
struct IsString<std::string_view> : true_type {};
struct StringAdapter<std::string_view, void> {
typedef SizedRamString AdaptedString;
static AdaptedString adapt(const std::string_view& s) {
return AdaptedString(s.data(), s.size());
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -5,13 +5,16 @@
#pragma once
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Strings/StringAdapter.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename T, typename Enable = void>
struct IsString : false_type {};
template <typename TChar>
struct IsString<const TChar*> : IsString<TChar*> {};
template <typename T>
struct IsString<
T, typename make_void<typename StringAdapter<T>::AdaptedString>::type>
: true_type {};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -12,30 +12,37 @@
namespace ARDUINOJSON_NAMESPACE {
class String : public SafeBoolIdom<String> {
// A string.
// https://arduinojson.org/v6/api/jsonstring/
class JsonString : public SafeBoolIdom<JsonString> {
public:
enum Ownership { Copied, Linked };
String() : _data(0), _size(0), _ownership(Linked) {}
JsonString() : _data(0), _size(0), _ownership(Linked) {}
String(const char* data, Ownership ownership = Linked)
JsonString(const char* data, Ownership ownership = Linked)
: _data(data), _size(data ? ::strlen(data) : 0), _ownership(ownership) {}
String(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) {}
// Returns a pointer to the characters.
const char* c_str() const {
return _data;
}
// Returns true if the string is null.
bool isNull() const {
return !_data;
}
// Returns true if the string is stored by address.
// Returns false if the string is stored by copy.
bool isLinked() const {
return _ownership == Linked;
}
// Returns length of the string.
size_t size() const {
return _size;
}
@@ -45,7 +52,8 @@ class String : public SafeBoolIdom<String> {
return _data ? safe_true() : safe_false();
}
friend bool operator==(String lhs, String rhs) {
// Returns true if strings are equal.
friend bool operator==(JsonString lhs, JsonString rhs) {
if (lhs._size != rhs._size)
return false;
if (lhs._data == rhs._data)
@@ -57,12 +65,13 @@ class String : public SafeBoolIdom<String> {
return memcmp(lhs._data, rhs._data, lhs._size) == 0;
}
friend bool operator!=(String lhs, String rhs) {
// Returns true if strings differs.
friend bool operator!=(JsonString lhs, JsonString rhs) {
return !(lhs == rhs);
}
#if ARDUINOJSON_ENABLE_STD_STREAM
friend std::ostream& operator<<(std::ostream& lhs, const String& rhs) {
friend std::ostream& operator<<(std::ostream& lhs, const JsonString& rhs) {
lhs.write(rhs.c_str(), static_cast<std::streamsize>(rhs.size()));
return lhs;
}

View File

@@ -4,53 +4,15 @@
#pragma once
#include <ArduinoJson/Memory/MemoryPool.hpp>
#include <ArduinoJson/Strings/String.hpp>
namespace ARDUINOJSON_NAMESPACE {
struct LinkStringStoragePolicy {
template <typename TAdaptedString, typename TCallback>
bool store(TAdaptedString str, MemoryPool *, TCallback callback) {
String storedString(str.data(), str.size(), String::Linked);
callback(storedString);
return !str.isNull();
}
namespace StringStoragePolicy {
struct Link {};
struct Copy {};
struct LinkOrCopy {
bool link;
};
struct CopyStringStoragePolicy {
template <typename TAdaptedString, typename TCallback>
bool store(TAdaptedString str, MemoryPool *pool, TCallback callback);
};
class LinkOrCopyStringStoragePolicy : LinkStringStoragePolicy,
CopyStringStoragePolicy {
public:
LinkOrCopyStringStoragePolicy(bool link) : _link(link) {}
template <typename TAdaptedString, typename TCallback>
bool store(TAdaptedString str, MemoryPool *pool, TCallback callback) {
if (_link)
return LinkStringStoragePolicy::store(str, pool, callback);
else
return CopyStringStoragePolicy::store(str, pool, callback);
}
private:
bool _link;
};
template <typename T>
inline CopyStringStoragePolicy getStringStoragePolicy(const T &) {
return CopyStringStoragePolicy();
}
inline LinkStringStoragePolicy getStringStoragePolicy(const char *) {
return LinkStringStoragePolicy();
}
inline LinkOrCopyStringStoragePolicy getStringStoragePolicy(const String &s) {
return LinkOrCopyStringStoragePolicy(s.isLinked());
}
} // namespace StringStoragePolicy
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,31 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
namespace ARDUINOJSON_NAMESPACE {
template <typename TString, typename Enable = void>
struct StringAdapter;
template <typename TString, typename Enable = void>
struct SizedStringAdapter;
template <typename TString>
typename StringAdapter<TString>::AdaptedString adaptString(const TString& s) {
return StringAdapter<TString>::adapt(s);
}
template <typename TChar>
typename StringAdapter<TChar*>::AdaptedString adaptString(TChar* p) {
return StringAdapter<TChar*>::adapt(p);
}
template <typename TChar>
typename SizedStringAdapter<TChar*>::AdaptedString adaptString(TChar* p,
size_t n) {
return SizedStringAdapter<TChar*>::adapt(p, n);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -4,6 +4,8 @@
#pragma once
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename T, typename Enable = void>
@@ -14,4 +16,7 @@ template <typename T1, typename T2>
class InvalidConversion; // Error here? See https://arduinojson.org/v6/invalid-conversion/
// clang-format on
template <typename T>
struct ConverterNeedsWriteableRef;
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -5,20 +5,20 @@
#pragma once
#include <ArduinoJson/Json/JsonSerializer.hpp>
#include <ArduinoJson/Variant/JsonVariantConst.hpp>
#include <ArduinoJson/Variant/VariantFunctions.hpp>
#include <ArduinoJson/Variant/VariantRef.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename T, typename Enable>
struct Converter {
static void toJson(const T& src, VariantRef dst) {
static void toJson(const T& src, JsonVariant dst) {
// clang-format off
convertToJson(src, dst); // Error here? See https://arduinojson.org/v6/unsupported-set/
// clang-format on
}
static T fromJson(VariantConstRef src) {
static T fromJson(JsonVariantConst src) {
// clang-format off
T result; // Error here? See https://arduinojson.org/v6/non-default-constructible/
convertFromJson(src, result); // Error here? See https://arduinojson.org/v6/unsupported-as/
@@ -26,7 +26,7 @@ struct Converter {
return result;
}
static bool checkJson(VariantConstRef src) {
static bool checkJson(JsonVariantConst src) {
T dummy = T();
// clang-format off
return canConvertFromJson(src, dummy); // Error here? See https://arduinojson.org/v6/unsupported-is/
@@ -37,112 +37,113 @@ struct Converter {
template <typename T>
struct Converter<
T, typename enable_if<is_integral<T>::value && !is_same<bool, T>::value &&
!is_same<char, T>::value>::type> {
static void toJson(T src, VariantRef dst) {
!is_same<char, T>::value>::type>
: private VariantAttorney {
static void toJson(T src, JsonVariant dst) {
VariantData* data = getData(dst);
ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
if (data)
data->setInteger(src);
}
static T fromJson(VariantConstRef src) {
static T fromJson(JsonVariantConst src) {
ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
const VariantData* data = getData(src);
return data ? data->asIntegral<T>() : T();
}
static bool checkJson(VariantConstRef src) {
static bool checkJson(JsonVariantConst src) {
const VariantData* data = getData(src);
return data && data->isInteger<T>();
}
};
template <typename T>
struct Converter<T, typename enable_if<is_enum<T>::value>::type> {
static void toJson(T src, VariantRef dst) {
dst.set(static_cast<Integer>(src));
struct Converter<T, typename enable_if<is_enum<T>::value>::type>
: private VariantAttorney {
static void toJson(T src, JsonVariant dst) {
dst.set(static_cast<JsonInteger>(src));
}
static T fromJson(VariantConstRef src) {
static T fromJson(JsonVariantConst src) {
const VariantData* data = getData(src);
return data ? static_cast<T>(data->asIntegral<int>()) : T();
}
static bool checkJson(VariantConstRef src) {
static bool checkJson(JsonVariantConst src) {
const VariantData* data = getData(src);
return data && data->isInteger<int>();
}
};
template <>
struct Converter<bool> {
static void toJson(bool src, VariantRef dst) {
struct Converter<bool> : private VariantAttorney {
static void toJson(bool src, JsonVariant dst) {
VariantData* data = getData(dst);
if (data)
data->setBoolean(src);
}
static bool fromJson(VariantConstRef src) {
static bool fromJson(JsonVariantConst src) {
const VariantData* data = getData(src);
return data ? data->asBoolean() : false;
}
static bool checkJson(VariantConstRef src) {
static bool checkJson(JsonVariantConst src) {
const VariantData* data = getData(src);
return data && data->isBoolean();
}
};
template <typename T>
struct Converter<T, typename enable_if<is_floating_point<T>::value>::type> {
static void toJson(T src, VariantRef dst) {
struct Converter<T, typename enable_if<is_floating_point<T>::value>::type>
: private VariantAttorney {
static void toJson(T src, JsonVariant dst) {
VariantData* data = getData(dst);
if (data)
data->setFloat(static_cast<Float>(src));
data->setFloat(static_cast<JsonFloat>(src));
}
static T fromJson(VariantConstRef src) {
static T fromJson(JsonVariantConst src) {
const VariantData* data = getData(src);
return data ? data->asFloat<T>() : false;
return data ? data->asFloat<T>() : 0;
}
static bool checkJson(VariantConstRef src) {
static bool checkJson(JsonVariantConst src) {
const VariantData* data = getData(src);
return data && data->isFloat();
}
};
template <>
struct Converter<const char*> {
static void toJson(const char* src, VariantRef dst) {
variantSetString(getData(dst), adaptString(src), getPool(dst),
getStringStoragePolicy(src));
struct Converter<const char*> : private VariantAttorney {
static void toJson(const char* src, JsonVariant dst) {
variantSetString(getData(dst), adaptString(src), getPool(dst));
}
static const char* fromJson(VariantConstRef src) {
static const char* fromJson(JsonVariantConst src) {
const VariantData* data = getData(src);
return data ? data->asString().c_str() : 0;
}
static bool checkJson(VariantConstRef src) {
static bool checkJson(JsonVariantConst src) {
const VariantData* data = getData(src);
return data && data->isString();
}
};
template <>
struct Converter<String> {
static void toJson(String src, VariantRef dst) {
variantSetString(getData(dst), adaptString(src), getPool(dst),
getStringStoragePolicy(src));
struct Converter<JsonString> : private VariantAttorney {
static void toJson(JsonString src, JsonVariant dst) {
variantSetString(getData(dst), adaptString(src), getPool(dst));
}
static String fromJson(VariantConstRef src) {
static JsonString fromJson(JsonVariantConst src) {
const VariantData* data = getData(src);
return data ? data->asString() : 0;
}
static bool checkJson(VariantConstRef src) {
static bool checkJson(JsonVariantConst src) {
const VariantData* data = getData(src);
return data && data->isString();
}
@@ -150,17 +151,16 @@ struct Converter<String> {
template <typename T>
inline typename enable_if<IsString<T>::value, bool>::type convertToJson(
const T& src, VariantRef dst) {
VariantData* data = getData(dst);
MemoryPool* pool = getPool(dst);
return variantSetString(data, adaptString(src), pool,
getStringStoragePolicy(src));
const T& src, JsonVariant dst) {
VariantData* data = VariantAttorney::getData(dst);
MemoryPool* pool = VariantAttorney::getPool(dst);
return variantSetString(data, adaptString(src), pool);
}
template <>
struct Converter<SerializedValue<const char*> > {
static void toJson(SerializedValue<const char*> src, VariantRef dst) {
VariantData* data = getData(dst);
static void toJson(SerializedValue<const char*> src, JsonVariant dst) {
VariantData* data = VariantAttorney::getData(dst);
if (data)
data->setLinkedRaw(src);
}
@@ -171,8 +171,9 @@ struct Converter<SerializedValue<const char*> > {
// SerializedValue<const __FlashStringHelper*>
template <typename T>
struct Converter<SerializedValue<T>,
typename enable_if<!is_same<const char*, T>::value>::type> {
static void toJson(SerializedValue<T> src, VariantRef dst) {
typename enable_if<!is_same<const char*, T>::value>::type>
: private VariantAttorney {
static void toJson(SerializedValue<T> src, JsonVariant dst) {
VariantData* data = getData(dst);
MemoryPool* pool = getPool(dst);
if (data)
@@ -183,14 +184,14 @@ struct Converter<SerializedValue<T>,
#if ARDUINOJSON_HAS_NULLPTR
template <>
struct Converter<decltype(nullptr)> {
static void toJson(decltype(nullptr), VariantRef dst) {
struct Converter<decltype(nullptr)> : private VariantAttorney {
static void toJson(decltype(nullptr), JsonVariant dst) {
variantSetNull(getData(dst));
}
static decltype(nullptr) fromJson(VariantConstRef) {
static decltype(nullptr) fromJson(JsonVariantConst) {
return nullptr;
}
static bool checkJson(VariantConstRef src) {
static bool checkJson(JsonVariantConst src) {
const VariantData* data = getData(src);
return data == 0 || data->isNull();
}
@@ -206,9 +207,10 @@ class MemoryPoolPrint : public Print {
pool->getFreeZone(&_string, &_capacity);
}
String str() {
JsonString str() {
ARDUINOJSON_ASSERT(_size < _capacity);
return String(_pool->saveStringFromFreeZone(_size), _size, String::Copied);
return JsonString(_pool->saveStringFromFreeZone(_size), _size,
JsonString::Copied);
}
size_t write(uint8_t c) {
@@ -240,9 +242,9 @@ class MemoryPoolPrint : public Print {
size_t _capacity;
};
inline void convertToJson(const ::Printable& src, VariantRef dst) {
MemoryPool* pool = getPool(dst);
VariantData* data = getData(dst);
inline void convertToJson(const ::Printable& src, JsonVariant dst) {
MemoryPool* pool = VariantAttorney::getPool(dst);
VariantData* data = VariantAttorney::getData(dst);
if (!pool || !data)
return;
MemoryPoolPrint print(pool);
@@ -259,48 +261,59 @@ inline void convertToJson(const ::Printable& src, VariantRef dst) {
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
inline void convertFromJson(VariantConstRef src, ::String& dst) {
String str = src.as<String>();
inline void convertFromJson(JsonVariantConst src, ::String& dst) {
JsonString str = src.as<JsonString>();
if (str)
dst = str.c_str();
else
serializeJson(src, dst);
}
inline bool canConvertFromJson(VariantConstRef src, const ::String&) {
return src.is<String>();
inline bool canConvertFromJson(JsonVariantConst src, const ::String&) {
return src.is<JsonString>();
}
#endif
#if ARDUINOJSON_ENABLE_STD_STRING
inline void convertFromJson(VariantConstRef src, std::string& dst) {
String str = src.as<String>();
inline void convertFromJson(JsonVariantConst src, std::string& dst) {
JsonString str = src.as<JsonString>();
if (str)
dst.assign(str.c_str(), str.size());
else
serializeJson(src, dst);
}
inline bool canConvertFromJson(VariantConstRef src, const std::string&) {
return src.is<String>();
inline bool canConvertFromJson(JsonVariantConst src, const std::string&) {
return src.is<JsonString>();
}
#endif
#if ARDUINOJSON_ENABLE_STRING_VIEW
inline void convertFromJson(VariantConstRef src, std::string_view& dst) {
String str = src.as<String>();
inline void convertFromJson(JsonVariantConst src, std::string_view& dst) {
JsonString str = src.as<JsonString>();
if (str) // the standard doesn't allow passing null to the constructor
dst = std::string_view(str.c_str(), str.size());
}
inline bool canConvertFromJson(VariantConstRef src, const std::string_view&) {
return src.is<String>();
inline bool canConvertFromJson(JsonVariantConst src, const std::string_view&) {
return src.is<JsonString>();
}
#endif
template <typename T>
struct ConverterNeedsWriteableRef {
protected: // <- to avoid GCC's "all member functions in class are private"
static int probe(T (*f)(JsonVariant));
static char probe(T (*f)(JsonVariantConst));
public:
static const bool value =
sizeof(probe(Converter<T>::fromJson)) == sizeof(int);
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,80 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Variant/VariantRefBase.hpp>
namespace ARDUINOJSON_NAMESPACE {
// A reference to a value in a JsonDocument.
// https://arduinojson.org/v6/api/jsonvariant/
class JsonVariant : public VariantRefBase<JsonVariant>,
public VariantOperators<JsonVariant> {
friend class VariantAttorney;
public:
// Creates an unbound reference.
JsonVariant() : _data(0), _pool(0) {}
// INTERNAL USE ONLY
JsonVariant(MemoryPool* pool, VariantData* data) : _data(data), _pool(pool) {}
private:
FORCE_INLINE MemoryPool* getPool() const {
return _pool;
}
FORCE_INLINE VariantData* getData() const {
return _data;
}
FORCE_INLINE VariantData* getOrCreateData() const {
return _data;
}
VariantData* _data;
MemoryPool* _pool;
};
template <>
struct Converter<JsonVariant> : private VariantAttorney {
static void toJson(JsonVariant src, JsonVariant dst) {
variantCopyFrom(getData(dst), getData(src), getPool(dst));
}
static JsonVariant fromJson(JsonVariant src) {
return src;
}
static InvalidConversion<JsonVariantConst, JsonVariant> fromJson(
JsonVariantConst);
static bool checkJson(JsonVariant src) {
VariantData* data = getData(src);
return !!data;
}
static bool checkJson(JsonVariantConst) {
return false;
}
};
template <>
struct Converter<JsonVariantConst> : private VariantAttorney {
static void toJson(JsonVariantConst src, JsonVariant dst) {
variantCopyFrom(getData(dst), getData(src), getPool(dst));
}
static JsonVariantConst fromJson(JsonVariantConst src) {
return JsonVariantConst(getData(src));
}
static bool checkJson(JsonVariantConst src) {
const VariantData* data = getData(src);
return !!data;
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,141 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <stddef.h>
#include <stdint.h> // for uint8_t
#include <ArduinoJson/Memory/MemoryPool.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Strings/IsString.hpp>
#include <ArduinoJson/Strings/StringAdapters.hpp>
#include <ArduinoJson/Variant/VariantAttorney.hpp>
#include <ArduinoJson/Variant/VariantFunctions.hpp>
#include <ArduinoJson/Variant/VariantOperators.hpp>
#include <ArduinoJson/Variant/VariantTag.hpp>
namespace ARDUINOJSON_NAMESPACE {
// Forward declarations.
class JsonArray;
class JsonObject;
// A read-only reference to a value in a JsonDocument
// https://arduinojson.org/v6/api/jsonarrayconst/
class JsonVariantConst : public VariantTag,
public VariantOperators<JsonVariantConst> {
friend class VariantAttorney;
public:
// Creates an unbound reference.
JsonVariantConst() : _data(0) {}
// INTERNAL USE ONLY
explicit JsonVariantConst(const VariantData* data) : _data(data) {}
// Returns true if the value is null or the reference is unbound.
// https://arduinojson.org/v6/api/jsonvariantconst/isnull/
FORCE_INLINE bool isNull() const {
return variantIsNull(_data);
}
// Returns true if the reference is unbound.
FORCE_INLINE bool isUnbound() const {
return !_data;
}
// Returns the number of bytes occupied by the value.
// https://arduinojson.org/v6/api/jsonvariantconst/memoryusage/
FORCE_INLINE size_t memoryUsage() const {
return _data ? _data->memoryUsage() : 0;
}
// Returns the depth (nesting level) of the value.
// https://arduinojson.org/v6/api/jsonvariantconst/nesting/
FORCE_INLINE size_t nesting() const {
return variantNesting(_data);
}
// Returns the size of the array or object.
// https://arduinojson.org/v6/api/jsonvariantconst/size/
size_t size() const {
return variantSize(_data);
}
// Casts the value to the specified type.
// https://arduinojson.org/v6/api/jsonvariantconst/as/
template <typename T>
FORCE_INLINE
typename enable_if<!is_same<T, char*>::value && !is_same<T, char>::value,
T>::type
as() const {
return Converter<T>::fromJson(*this);
}
// Returns true if the value is of the specified type.
// https://arduinojson.org/v6/api/jsonvariantconst/is/
template <typename T>
FORCE_INLINE
typename enable_if<!is_same<T, char*>::value && !is_same<T, char>::value,
bool>::type
is() const {
return Converter<T>::checkJson(*this);
}
template <typename T>
FORCE_INLINE operator T() const {
return as<T>();
}
// Gets array's element at specified index.
// https://arduinojson.org/v6/api/jsonvariantconst/subscript/
FORCE_INLINE JsonVariantConst operator[](size_t index) const {
return JsonVariantConst(variantGetElement(_data, index));
}
// Gets object's member with specified key.
// https://arduinojson.org/v6/api/jsonvariantconst/subscript/
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value, JsonVariantConst>::type
operator[](const TString& key) const {
return JsonVariantConst(variantGetMember(_data, adaptString(key)));
}
// Gets object's member with specified key.
// https://arduinojson.org/v6/api/jsonvariantconst/subscript/
template <typename TChar>
FORCE_INLINE
typename enable_if<IsString<TChar*>::value, JsonVariantConst>::type
operator[](TChar* key) const {
return JsonVariantConst(variantGetMember(_data, adaptString(key)));
}
// Returns true if tge object contains the specified key.
// https://arduinojson.org/v6/api/jsonvariantconst/containskey/
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value, bool>::type
containsKey(const TString& key) const {
return variantGetMember(getData(), adaptString(key)) != 0;
}
// Returns true if tge object contains the specified key.
// https://arduinojson.org/v6/api/jsonvariantconst/containskey/
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value, bool>::type
containsKey(TChar* key) const {
return variantGetMember(getData(), adaptString(key)) != 0;
}
protected:
const VariantData* getData() const {
return _data;
}
private:
const VariantData* _data;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -23,12 +23,11 @@ struct SlotKeySetter {
VariantSlot* _instance;
};
template <typename TAdaptedString, typename TStoragePolicy>
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool,
TStoragePolicy storage) {
template <typename TAdaptedString>
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) {
if (!var)
return false;
return storage.store(key, pool, SlotKeySetter(var));
return storeString(pool, key, SlotKeySetter(var));
}
inline size_t slotSize(const VariantSlot* var) {

View File

@@ -0,0 +1,48 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Polyfills/attributes.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Variant/VariantTo.hpp>
#include "JsonVariantConst.hpp"
namespace ARDUINOJSON_NAMESPACE {
// Grants access to the internal variant API
class VariantAttorney {
// Tells whether getData() returns a const pointer
template <typename TClient>
struct ResultOfGetData {
protected: // <- to avoid GCC's "all member functions in class are private"
static int probe(const VariantData*);
static char probe(VariantData*);
static TClient& client;
public:
typedef typename conditional<sizeof(probe(client.getData())) == sizeof(int),
const VariantData*, VariantData*>::type type;
};
public:
template <typename TClient>
FORCE_INLINE static MemoryPool* getPool(TClient& client) {
return client.getPool();
}
template <typename TClient>
FORCE_INLINE static typename ResultOfGetData<TClient>::type getData(
TClient& client) {
return client.getData();
}
template <typename TClient>
FORCE_INLINE static VariantData* getOrCreateData(TClient& client) {
return client.getOrCreateData();
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -5,7 +5,6 @@
#pragma once
#include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Misc/Visitable.hpp>
#include <ArduinoJson/Numbers/arithmeticCompare.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Strings/StringAdapters.hpp>
@@ -27,7 +26,7 @@ struct Comparer<T, typename enable_if<IsString<T>::value>::type>
explicit Comparer(T 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));
if (i < 0)
return COMPARE_RESULT_GREATER;
@@ -53,20 +52,20 @@ struct Comparer<T, typename enable_if<is_integral<T>::value ||
explicit Comparer(T value) : rhs(value) {}
CompareResult visitFloat(Float lhs) {
CompareResult visitFloat(JsonFloat lhs) {
return arithmeticCompare(lhs, rhs);
}
CompareResult visitSignedInteger(Integer lhs) {
CompareResult visitSignedInteger(JsonInteger lhs) {
return arithmeticCompare(lhs, rhs);
}
CompareResult visitUnsignedInteger(UInt lhs) {
CompareResult visitUnsignedInteger(JsonUInt lhs) {
return arithmeticCompare(lhs, rhs);
}
CompareResult visitBoolean(bool lhs) {
return visitUnsignedInteger(static_cast<UInt>(lhs));
return visitUnsignedInteger(static_cast<JsonUInt>(lhs));
}
};
@@ -84,12 +83,12 @@ struct Comparer<decltype(nullptr), void> : NullComparer {
#endif
struct ArrayComparer : ComparerBase {
const CollectionData *_rhs;
const CollectionData* _rhs;
explicit ArrayComparer(const CollectionData &rhs) : _rhs(&rhs) {}
explicit ArrayComparer(const CollectionData& rhs) : _rhs(&rhs) {}
CompareResult visitArray(const CollectionData &lhs) {
if (lhs.equalsArray(*_rhs))
CompareResult visitArray(const CollectionData& lhs) {
if (JsonArrayConst(&lhs) == JsonArrayConst(_rhs))
return COMPARE_RESULT_EQUAL;
else
return COMPARE_RESULT_DIFFER;
@@ -97,12 +96,12 @@ struct ArrayComparer : ComparerBase {
};
struct ObjectComparer : ComparerBase {
const CollectionData *_rhs;
const CollectionData* _rhs;
explicit ObjectComparer(const CollectionData &rhs) : _rhs(&rhs) {}
explicit ObjectComparer(const CollectionData& rhs) : _rhs(&rhs) {}
CompareResult visitObject(const CollectionData &lhs) {
if (lhs.equalsObject(*_rhs))
CompareResult visitObject(const CollectionData& lhs) {
if (JsonObjectConst(&lhs) == JsonObjectConst(_rhs))
return COMPARE_RESULT_EQUAL;
else
return COMPARE_RESULT_DIFFER;
@@ -110,13 +109,13 @@ struct ObjectComparer : ComparerBase {
};
struct RawComparer : ComparerBase {
const char *_rhsData;
const char* _rhsData;
size_t _rhsSize;
explicit RawComparer(const char *rhsData, size_t rhsSize)
explicit RawComparer(const char* rhsData, size_t rhsSize)
: _rhsData(rhsData), _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;
int n = memcmp(lhsData, _rhsData, size);
if (n < 0)
@@ -128,45 +127,43 @@ struct RawComparer : ComparerBase {
}
};
template <typename T>
struct Comparer<T, typename enable_if<IsVisitable<T>::value>::type>
: ComparerBase {
const T *rhs; // TODO: should be a VariantConstRef
struct VariantComparer : ComparerBase {
const VariantData* rhs;
explicit Comparer(const T &value) : rhs(&value) {}
explicit VariantComparer(const VariantData* value) : rhs(value) {}
CompareResult visitArray(const CollectionData &lhs) {
CompareResult visitArray(const CollectionData& lhs) {
ArrayComparer comparer(lhs);
return accept(comparer);
}
CompareResult visitObject(const CollectionData &lhs) {
CompareResult visitObject(const CollectionData& lhs) {
ObjectComparer comparer(lhs);
return accept(comparer);
}
CompareResult visitFloat(Float lhs) {
Comparer<Float> comparer(lhs);
CompareResult visitFloat(JsonFloat lhs) {
Comparer<JsonFloat> comparer(lhs);
return accept(comparer);
}
CompareResult visitString(const char *lhs, size_t) {
Comparer<const char *> comparer(lhs);
CompareResult visitString(const char* lhs, size_t) {
Comparer<const char*> comparer(lhs);
return accept(comparer);
}
CompareResult visitRawJson(const char *lhsData, size_t lhsSize) {
CompareResult visitRawJson(const char* lhsData, size_t lhsSize) {
RawComparer comparer(lhsData, lhsSize);
return accept(comparer);
}
CompareResult visitSignedInteger(Integer lhs) {
Comparer<Integer> comparer(lhs);
CompareResult visitSignedInteger(JsonInteger lhs) {
Comparer<JsonInteger> comparer(lhs);
return accept(comparer);
}
CompareResult visitUnsignedInteger(UInt lhs) {
Comparer<UInt> comparer(lhs);
CompareResult visitUnsignedInteger(JsonUInt lhs) {
Comparer<JsonUInt> comparer(lhs);
return accept(comparer);
}
@@ -182,8 +179,8 @@ struct Comparer<T, typename enable_if<IsVisitable<T>::value>::type>
private:
template <typename TComparer>
CompareResult accept(TComparer &comparer) {
CompareResult reversedResult = rhs->accept(comparer);
CompareResult accept(TComparer& comparer) {
CompareResult reversedResult = variantAccept(rhs, comparer);
switch (reversedResult) {
case COMPARE_RESULT_GREATER:
return COMPARE_RESULT_LESS;
@@ -195,14 +192,18 @@ struct Comparer<T, typename enable_if<IsVisitable<T>::value>::type>
}
};
template <typename T1, typename T2>
CompareResult compare(const T1 &lhs, const T2 &rhs) {
Comparer<T2> comparer(rhs);
return lhs.accept(comparer);
}
template <typename T>
struct Comparer<
T, typename enable_if<is_convertible<T, JsonVariantConst>::value>::type>
: VariantComparer {
explicit Comparer(const T& value)
: VariantComparer(VariantAttorney::getData(value)) {}
};
inline int variantCompare(const VariantData *a, const VariantData *b) {
return compare(VariantConstRef(a), VariantConstRef(b));
template <typename T>
CompareResult compare(JsonVariantConst lhs, const T& rhs) {
Comparer<T> comparer(rhs);
return variantAccept(VariantAttorney::getData(lhs), comparer);
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -7,8 +7,8 @@
#include <stddef.h> // size_t
#include <ArduinoJson/Collection/CollectionData.hpp>
#include <ArduinoJson/Numbers/Float.hpp>
#include <ArduinoJson/Numbers/Integer.hpp>
#include <ArduinoJson/Numbers/JsonFloat.hpp>
#include <ArduinoJson/Numbers/JsonInteger.hpp>
namespace ARDUINOJSON_NAMESPACE {
@@ -39,18 +39,18 @@ enum {
};
struct RawData {
const char *data;
const char* data;
size_t size;
};
union VariantContent {
Float asFloat;
JsonFloat asFloat;
bool asBoolean;
UInt asUnsignedInteger;
Integer asSignedInteger;
JsonUInt asUnsignedInteger;
JsonInteger asSignedInteger;
CollectionData asCollection;
struct {
const char *data;
const char* data;
size_t size;
} asString;
};

View File

@@ -7,7 +7,7 @@
#include <ArduinoJson/Memory/MemoryPool.hpp>
#include <ArduinoJson/Misc/SerializedValue.hpp>
#include <ArduinoJson/Numbers/convertNumber.hpp>
#include <ArduinoJson/Strings/String.hpp>
#include <ArduinoJson/Strings/JsonString.hpp>
#include <ArduinoJson/Strings/StringAdapters.hpp>
#include <ArduinoJson/Variant/VariantContent.hpp>
@@ -37,8 +37,13 @@ class VariantData {
_flags = VALUE_IS_NULL;
}
void operator=(const VariantData& src) {
_content = src._content;
_flags = uint8_t((_flags & OWNED_KEY_BIT) | (src._flags & ~OWNED_KEY_BIT));
}
template <typename TVisitor>
typename TVisitor::result_type accept(TVisitor &visitor) const {
typename TVisitor::result_type accept(TVisitor& visitor) const {
switch (type()) {
case VALUE_IS_FLOAT:
return visitor.visitFloat(_content.asFloat);
@@ -79,27 +84,31 @@ class VariantData {
template <typename T>
T asFloat() const;
String asString() const;
JsonString asString() const;
bool asBoolean() const;
CollectionData *asArray() {
CollectionData* asArray() {
return isArray() ? &_content.asCollection : 0;
}
const CollectionData *asArray() const {
return const_cast<VariantData *>(this)->asArray();
const CollectionData* asArray() const {
return const_cast<VariantData*>(this)->asArray();
}
CollectionData *asObject() {
const CollectionData* asCollection() const {
return isCollection() ? &_content.asCollection : 0;
}
CollectionData* asObject() {
return isObject() ? &_content.asCollection : 0;
}
const CollectionData *asObject() const {
return const_cast<VariantData *>(this)->asObject();
const CollectionData* asObject() const {
return const_cast<VariantData*>(this)->asObject();
}
bool copyFrom(const VariantData &src, MemoryPool *pool);
bool copyFrom(const VariantData& src, MemoryPool* pool);
bool isArray() const {
return (_flags & VALUE_IS_ARRAY) != 0;
@@ -163,12 +172,12 @@ class VariantData {
_content.asBoolean = value;
}
void setFloat(Float value) {
void setFloat(JsonFloat value) {
setType(VALUE_IS_FLOAT);
_content.asFloat = value;
}
void setLinkedRaw(SerializedValue<const char *> value) {
void setLinkedRaw(SerializedValue<const char*> value) {
if (value.data()) {
setType(VALUE_IS_LINKED_RAW);
_content.asString.data = value.data();
@@ -179,8 +188,8 @@ class VariantData {
}
template <typename T>
bool storeOwnedRaw(SerializedValue<T> value, MemoryPool *pool) {
const char *dup = pool->saveString(adaptString(value.data(), value.size()));
bool storeOwnedRaw(SerializedValue<T> value, MemoryPool* pool) {
const char* dup = pool->saveString(adaptString(value.data(), value.size()));
if (dup) {
setType(VALUE_IS_OWNED_RAW);
_content.asString.data = dup;
@@ -195,7 +204,7 @@ class VariantData {
template <typename T>
typename enable_if<is_unsigned<T>::value>::type setInteger(T value) {
setType(VALUE_IS_UNSIGNED_INTEGER);
_content.asUnsignedInteger = static_cast<UInt>(value);
_content.asUnsignedInteger = static_cast<JsonUInt>(value);
}
template <typename T>
@@ -208,7 +217,7 @@ class VariantData {
setType(VALUE_IS_NULL);
}
void setString(String s) {
void setString(JsonString s) {
ARDUINOJSON_ASSERT(s);
if (s.isLinked())
setType(VALUE_IS_LINKED_STRING);
@@ -218,13 +227,13 @@ class VariantData {
_content.asString.size = s.size();
}
CollectionData &toArray() {
CollectionData& toArray() {
setType(VALUE_IS_ARRAY);
_content.asCollection.clear();
return _content.asCollection;
}
CollectionData &toObject() {
CollectionData& toObject() {
setType(VALUE_IS_OBJECT);
_content.asCollection.clear();
return _content.asCollection;
@@ -245,15 +254,11 @@ class VariantData {
}
}
size_t nesting() const {
return isCollection() ? _content.asCollection.nesting() : 0;
}
size_t size() const {
return isCollection() ? _content.asCollection.size() : 0;
}
VariantData *addElement(MemoryPool *pool) {
VariantData* addElement(MemoryPool* pool) {
if (isNull())
toArray();
if (!isArray())
@@ -261,11 +266,12 @@ class VariantData {
return _content.asCollection.addElement(pool);
}
VariantData *getElement(size_t index) const {
return isArray() ? _content.asCollection.getElement(index) : 0;
VariantData* getElement(size_t index) const {
const CollectionData* col = asArray();
return col ? col->getElement(index) : 0;
}
VariantData *getOrAddElement(size_t index, MemoryPool *pool) {
VariantData* getOrAddElement(size_t index, MemoryPool* pool) {
if (isNull())
toArray();
if (!isArray())
@@ -274,18 +280,18 @@ class VariantData {
}
template <typename TAdaptedString>
VariantData *getMember(TAdaptedString key) const {
return isObject() ? _content.asCollection.getMember(key) : 0;
VariantData* getMember(TAdaptedString key) const {
const CollectionData* col = asObject();
return col ? col->getMember(key) : 0;
}
template <typename TAdaptedString, typename TStoragePolicy>
VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool,
TStoragePolicy storage_policy) {
template <typename TAdaptedString>
VariantData* getOrAddMember(TAdaptedString key, MemoryPool* pool) {
if (isNull())
toObject();
if (!isObject())
return 0;
return _content.asCollection.getOrAddMember(key, pool, storage_policy);
return _content.asCollection.getOrAddMember(key, pool);
}
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) {
@@ -299,15 +305,14 @@ class VariantData {
return _flags & VALUE_MASK;
}
template <typename TAdaptedString, typename TStoragePolicy>
inline bool storeString(TAdaptedString value, MemoryPool *pool,
TStoragePolicy storage) {
template <typename TAdaptedString>
inline bool setString(TAdaptedString value, MemoryPool* pool) {
if (value.isNull()) {
setNull();
return true;
}
return storage.store(value, pool, VariantStringSetter(this));
return storeString(pool, value, VariantStringSetter(this));
}
private:
@@ -317,7 +322,7 @@ class VariantData {
}
struct VariantStringSetter {
VariantStringSetter(VariantData *instance) : _instance(instance) {}
VariantStringSetter(VariantData* instance) : _instance(instance) {}
template <typename TStoredString>
void operator()(TStoredString s) {
@@ -327,7 +332,7 @@ class VariantData {
_instance->setNull();
}
VariantData *_instance;
VariantData* _instance;
};
};

View File

@@ -7,32 +7,21 @@
#include <ArduinoJson/Polyfills/attributes.hpp>
#include <ArduinoJson/Strings/StoragePolicy.hpp>
#include <ArduinoJson/Variant/VariantData.hpp>
#include <ArduinoJson/Variant/Visitor.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename TVisitor>
inline typename TVisitor::result_type variantAccept(const VariantData *var,
TVisitor &visitor) {
inline typename TVisitor::result_type variantAccept(const VariantData* var,
TVisitor& visitor) {
if (var != 0)
return var->accept(visitor);
else
return visitor.visitNull();
}
inline const CollectionData *variantAsArray(const VariantData *var) {
return var != 0 ? var->asArray() : 0;
}
inline const CollectionData *variantAsObject(const VariantData *var) {
return var != 0 ? var->asObject() : 0;
}
inline CollectionData *variantAsObject(VariantData *var) {
return var != 0 ? var->asObject() : 0;
}
inline bool variantCopyFrom(VariantData *dst, const VariantData *src,
MemoryPool *pool) {
inline bool variantCopyFrom(VariantData* dst, const VariantData* src,
MemoryPool* pool) {
if (!dst)
return false;
if (!src) {
@@ -42,68 +31,83 @@ inline bool variantCopyFrom(VariantData *dst, const VariantData *src,
return dst->copyFrom(*src, pool);
}
inline int variantCompare(const VariantData *a, const VariantData *b);
inline void variantSetNull(VariantData *var) {
inline void variantSetNull(VariantData* var) {
if (!var)
return;
var->setNull();
}
template <typename TAdaptedString, typename TStoragePolicy>
inline bool variantSetString(VariantData *var, TAdaptedString value,
MemoryPool *pool, TStoragePolicy storage_policy) {
return var != 0 ? var->storeString(value, pool, storage_policy) : 0;
template <typename TAdaptedString>
inline bool variantSetString(VariantData* var, TAdaptedString value,
MemoryPool* pool) {
return var != 0 ? var->setString(value, pool) : 0;
}
inline size_t variantSize(const VariantData *var) {
inline size_t variantSize(const VariantData* var) {
return var != 0 ? var->size() : 0;
}
inline CollectionData *variantToArray(VariantData *var) {
inline CollectionData* variantToArray(VariantData* var) {
if (!var)
return 0;
return &var->toArray();
}
inline CollectionData *variantToObject(VariantData *var) {
inline CollectionData* variantToObject(VariantData* var) {
if (!var)
return 0;
return &var->toObject();
}
inline NO_INLINE VariantData *variantAddElement(VariantData *var,
MemoryPool *pool) {
inline VariantData* variantGetElement(const VariantData* var, size_t index) {
return var != 0 ? var->getElement(index) : 0;
}
inline NO_INLINE VariantData* variantAddElement(VariantData* var,
MemoryPool* pool) {
return var != 0 ? var->addElement(pool) : 0;
}
inline NO_INLINE VariantData *variantGetOrAddElement(VariantData *var,
inline NO_INLINE VariantData* variantGetOrAddElement(VariantData* var,
size_t index,
MemoryPool *pool) {
MemoryPool* pool) {
return var != 0 ? var->getOrAddElement(index, pool) : 0;
}
template <typename TChar>
NO_INLINE VariantData *variantGetOrAddMember(VariantData *var, TChar *key,
MemoryPool *pool) {
template <typename TAdaptedString>
VariantData* variantGetMember(const VariantData* var, TAdaptedString key) {
if (!var)
return 0;
return var->getOrAddMember(adaptString(key), pool,
getStringStoragePolicy(key));
return var->getMember(key);
}
template <typename TString>
NO_INLINE VariantData *variantGetOrAddMember(VariantData *var,
const TString &key,
MemoryPool *pool) {
template <typename TAdaptedString>
VariantData* variantGetOrAddMember(VariantData* var, TAdaptedString key,
MemoryPool* pool) {
if (!var)
return 0;
return var->getOrAddMember(adaptString(key), pool,
getStringStoragePolicy(key));
return var->getOrAddMember(key, pool);
}
inline bool variantIsNull(const VariantData *var) {
inline bool variantIsNull(const VariantData* var) {
return var == 0 || var->isNull();
}
inline size_t variantNesting(const VariantData* var) {
if (!var)
return 0;
const CollectionData* collection = var->asCollection();
if (!collection)
return 0;
size_t maxChildNesting = 0;
for (const VariantSlot* s = collection->head(); s; s = s->next()) {
size_t childNesting = variantNesting(s->data());
if (childNesting > maxChildNesting)
maxChildNesting = childNesting;
}
return maxChildNesting + 1;
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -4,12 +4,12 @@
#pragma once
#include <ArduinoJson/Array/ArrayRef.hpp>
#include <ArduinoJson/Array/JsonArray.hpp>
#include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Numbers/convertNumber.hpp>
#include <ArduinoJson/Numbers/parseNumber.hpp>
#include <ArduinoJson/Object/ObjectRef.hpp>
#include <ArduinoJson/Variant/VariantRef.hpp>
#include <ArduinoJson/Object/JsonObject.hpp>
#include <ArduinoJson/Variant/JsonVariant.hpp>
#include <string.h> // for strcmp
@@ -70,29 +70,28 @@ inline T VariantData::asFloat() const {
}
}
inline String VariantData::asString() const {
inline JsonString VariantData::asString() const {
switch (type()) {
case VALUE_IS_LINKED_STRING:
return String(_content.asString.data, _content.asString.size,
String::Linked);
return JsonString(_content.asString.data, _content.asString.size,
JsonString::Linked);
case VALUE_IS_OWNED_STRING:
return String(_content.asString.data, _content.asString.size,
String::Copied);
return JsonString(_content.asString.data, _content.asString.size,
JsonString::Copied);
default:
return String();
return JsonString();
}
}
inline bool VariantData::copyFrom(const VariantData &src, MemoryPool *pool) {
inline bool VariantData::copyFrom(const VariantData& src, MemoryPool* pool) {
switch (src.type()) {
case VALUE_IS_ARRAY:
return toArray().copyFrom(src._content.asCollection, pool);
case VALUE_IS_OBJECT:
return toObject().copyFrom(src._content.asCollection, pool);
case VALUE_IS_OWNED_STRING: {
String value = src.asString();
return storeString(adaptString(value), pool,
getStringStoragePolicy(value));
JsonString value = src.asString();
return setString(adaptString(value), pool);
}
case VALUE_IS_OWNED_RAW:
return storeOwnedRaw(
@@ -105,80 +104,48 @@ inline bool VariantData::copyFrom(const VariantData &src, MemoryPool *pool) {
}
}
template <typename T>
inline typename enable_if<is_same<T, ArrayRef>::value, ArrayRef>::type
VariantRef::to() const {
return ArrayRef(_pool, variantToArray(_data));
template <typename TDerived>
inline JsonVariant VariantRefBase<TDerived>::add() const {
return JsonVariant(getPool(),
variantAddElement(getOrCreateData(), getPool()));
}
template <typename T>
typename enable_if<is_same<T, ObjectRef>::value, ObjectRef>::type
VariantRef::to() const {
return ObjectRef(_pool, variantToObject(_data));
template <typename TDerived>
inline JsonVariant VariantRefBase<TDerived>::getVariant() const {
return JsonVariant(getPool(), getData());
}
template <typename TDerived>
inline JsonVariant VariantRefBase<TDerived>::getOrCreateVariant() const {
return JsonVariant(getPool(), getOrCreateData());
}
template <typename TDerived>
template <typename T>
typename enable_if<is_same<T, VariantRef>::value, VariantRef>::type
VariantRef::to() const {
variantSetNull(_data);
inline typename enable_if<is_same<T, JsonArray>::value, JsonArray>::type
VariantRefBase<TDerived>::to() const {
return JsonArray(getPool(), variantToArray(getOrCreateData()));
}
template <typename TDerived>
template <typename T>
typename enable_if<is_same<T, JsonObject>::value, JsonObject>::type
VariantRefBase<TDerived>::to() const {
return JsonObject(getPool(), variantToObject(getOrCreateData()));
}
template <typename TDerived>
template <typename T>
typename enable_if<is_same<T, JsonVariant>::value, JsonVariant>::type
VariantRefBase<TDerived>::to() const {
variantSetNull(getOrCreateData());
return *this;
}
inline VariantConstRef VariantConstRef::getElement(size_t index) const {
return ArrayConstRef(_data != 0 ? _data->asArray() : 0)[index];
}
inline VariantRef VariantRef::addElement() const {
return VariantRef(_pool, variantAddElement(_data, _pool));
}
inline VariantRef VariantRef::getElement(size_t index) const {
return VariantRef(_pool, _data != 0 ? _data->getElement(index) : 0);
}
inline VariantRef VariantRef::getOrAddElement(size_t index) const {
return VariantRef(_pool, variantGetOrAddElement(_data, index, _pool));
}
template <typename TChar>
inline VariantRef VariantRef::getMember(TChar *key) const {
return VariantRef(_pool, _data != 0 ? _data->getMember(adaptString(key)) : 0);
}
template <typename TString>
inline typename enable_if<IsString<TString>::value, VariantRef>::type
VariantRef::getMember(const TString &key) const {
return VariantRef(_pool, _data != 0 ? _data->getMember(adaptString(key)) : 0);
}
template <typename TChar>
inline VariantRef VariantRef::getOrAddMember(TChar *key) const {
return VariantRef(_pool, variantGetOrAddMember(_data, key, _pool));
}
template <typename TString>
inline VariantRef VariantRef::getOrAddMember(const TString &key) const {
return VariantRef(_pool, variantGetOrAddMember(_data, key, _pool));
}
inline VariantConstRef operator|(VariantConstRef preferedValue,
VariantConstRef defaultValue) {
return preferedValue ? preferedValue : defaultValue;
}
// Out of class definition to avoid #1560
inline bool VariantRef::set(char value) const {
return set(static_cast<signed char>(value));
}
// TODO: move somewhere else
template <typename TAdaptedString, typename TCallback>
bool CopyStringStoragePolicy::store(TAdaptedString str, MemoryPool *pool,
TCallback callback) {
const char *copy = pool->saveString(str);
String storedString(copy, str.size(), String::Copied);
callback(storedString);
return copy != 0;
template <typename TDerived>
inline void convertToJson(const VariantRefBase<TDerived>& src,
JsonVariant dst) {
dst.set(src.template as<JsonVariantConst>());
}
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -4,7 +4,6 @@
#pragma once
#include <ArduinoJson/Misc/Visitable.hpp>
#include <ArduinoJson/Numbers/arithmeticCompare.hpp>
#include <ArduinoJson/Polyfills/attributes.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
@@ -12,12 +11,17 @@
namespace ARDUINOJSON_NAMESPACE {
template <typename T1, typename T2>
CompareResult compare(const T1 &lhs, const T2 &rhs); // VariantCompare.cpp
class JsonVariantConst;
template <typename T>
CompareResult compare(JsonVariantConst lhs,
const T& rhs); // VariantCompare.cpp
struct VariantOperatorTag {};
template <typename TVariant>
struct VariantOperators {
// Returns the default value if the VariantRef is unbound or incompatible
struct VariantOperators : VariantOperatorTag {
// Returns the default value if the JsonVariant is unbound or incompatible
//
// int operator|(JsonVariant, int)
// float operator|(JsonVariant, float)
@@ -25,7 +29,7 @@ struct VariantOperators {
template <typename T>
friend
typename enable_if<!IsVariant<T>::value && !is_array<T>::value, T>::type
operator|(const TVariant &variant, const T &defaultValue) {
operator|(const TVariant& variant, const T& defaultValue) {
if (variant.template is<T>())
return variant.template as<T>();
else
@@ -33,18 +37,18 @@ struct VariantOperators {
}
//
// const char* operator|(JsonVariant, const char*)
friend const char *operator|(const TVariant &variant,
const char *defaultValue) {
if (variant.template is<const char *>())
return variant.template as<const char *>();
friend const char* operator|(const TVariant& variant,
const char* defaultValue) {
if (variant.template is<const char*>())
return variant.template as<const char*>();
else
return defaultValue;
}
//
// JsonVariant operator|(JsonVariant, JsonVariant)
template <typename T>
friend typename enable_if<IsVariant<T>::value, typename T::variant_type>::type
operator|(const TVariant &variant, T defaultValue) {
friend typename enable_if<IsVariant<T>::value, JsonVariantConst>::type
operator|(const TVariant& variant, T defaultValue) {
if (variant)
return variant;
else
@@ -53,127 +57,133 @@ struct VariantOperators {
// value == TVariant
template <typename T>
friend bool operator==(T *lhs, TVariant rhs) {
friend bool operator==(T* lhs, TVariant rhs) {
return compare(rhs, lhs) == COMPARE_RESULT_EQUAL;
}
template <typename T>
friend bool operator==(const T &lhs, TVariant rhs) {
friend bool operator==(const T& lhs, TVariant rhs) {
return compare(rhs, lhs) == COMPARE_RESULT_EQUAL;
}
// TVariant == value
template <typename T>
friend bool operator==(TVariant lhs, T *rhs) {
friend bool operator==(TVariant lhs, T* rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
}
template <typename T>
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator==(
TVariant lhs, const T &rhs) {
friend
typename enable_if<!is_base_of<VariantOperatorTag, T>::value, bool>::type
operator==(TVariant lhs, const T& rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_EQUAL;
}
// value != TVariant
template <typename T>
friend bool operator!=(T *lhs, TVariant rhs) {
friend bool operator!=(T* lhs, TVariant rhs) {
return compare(rhs, lhs) != COMPARE_RESULT_EQUAL;
}
template <typename T>
friend bool operator!=(const T &lhs, TVariant rhs) {
friend bool operator!=(const T& lhs, TVariant rhs) {
return compare(rhs, lhs) != COMPARE_RESULT_EQUAL;
}
// TVariant != value
template <typename T>
friend bool operator!=(TVariant lhs, T *rhs) {
friend bool operator!=(TVariant lhs, T* rhs) {
return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
}
template <typename T>
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator!=(
TVariant lhs, const T &rhs) {
friend
typename enable_if<!is_base_of<VariantOperatorTag, T>::value, bool>::type
operator!=(TVariant lhs, const T& rhs) {
return compare(lhs, rhs) != COMPARE_RESULT_EQUAL;
}
// value < TVariant
template <typename T>
friend bool operator<(T *lhs, TVariant rhs) {
friend bool operator<(T* lhs, TVariant rhs) {
return compare(rhs, lhs) == COMPARE_RESULT_GREATER;
}
template <typename T>
friend bool operator<(const T &lhs, TVariant rhs) {
friend bool operator<(const T& lhs, TVariant rhs) {
return compare(rhs, lhs) == COMPARE_RESULT_GREATER;
}
// TVariant < value
template <typename T>
friend bool operator<(TVariant lhs, T *rhs) {
friend bool operator<(TVariant lhs, T* rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_LESS;
}
template <typename T>
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator<(
TVariant lhs, const T &rhs) {
friend
typename enable_if<!is_base_of<VariantOperatorTag, T>::value, bool>::type
operator<(TVariant lhs, const T& rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_LESS;
}
// value <= TVariant
template <typename T>
friend bool operator<=(T *lhs, TVariant rhs) {
friend bool operator<=(T* lhs, TVariant rhs) {
return (compare(rhs, lhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
}
template <typename T>
friend bool operator<=(const T &lhs, TVariant rhs) {
friend bool operator<=(const T& lhs, TVariant rhs) {
return (compare(rhs, lhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
}
// TVariant <= value
template <typename T>
friend bool operator<=(TVariant lhs, T *rhs) {
friend bool operator<=(TVariant lhs, T* rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
}
template <typename T>
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator<=(
TVariant lhs, const T &rhs) {
friend
typename enable_if<!is_base_of<VariantOperatorTag, T>::value, bool>::type
operator<=(TVariant lhs, const T& rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
}
// value > TVariant
template <typename T>
friend bool operator>(T *lhs, TVariant rhs) {
friend bool operator>(T* lhs, TVariant rhs) {
return compare(rhs, lhs) == COMPARE_RESULT_LESS;
}
template <typename T>
friend bool operator>(const T &lhs, TVariant rhs) {
friend bool operator>(const T& lhs, TVariant rhs) {
return compare(rhs, lhs) == COMPARE_RESULT_LESS;
}
// TVariant > value
template <typename T>
friend bool operator>(TVariant lhs, T *rhs) {
friend bool operator>(TVariant lhs, T* rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
}
template <typename T>
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator>(
TVariant lhs, const T &rhs) {
friend
typename enable_if<!is_base_of<VariantOperatorTag, T>::value, bool>::type
operator>(TVariant lhs, const T& rhs) {
return compare(lhs, rhs) == COMPARE_RESULT_GREATER;
}
// value >= TVariant
template <typename T>
friend bool operator>=(T *lhs, TVariant rhs) {
friend bool operator>=(T* lhs, TVariant rhs) {
return (compare(rhs, lhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
}
template <typename T>
friend bool operator>=(const T &lhs, TVariant rhs) {
friend bool operator>=(const T& lhs, TVariant rhs) {
return (compare(rhs, lhs) & COMPARE_RESULT_LESS_OR_EQUAL) != 0;
}
// TVariant >= value
template <typename T>
friend bool operator>=(TVariant lhs, T *rhs) {
friend bool operator>=(TVariant lhs, T* rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
}
template <typename T>
friend typename enable_if<!IsVisitable<T>::value, bool>::type operator>=(
TVariant lhs, const T &rhs) {
friend
typename enable_if<!is_base_of<VariantOperatorTag, T>::value, bool>::type
operator>=(TVariant lhs, const T& rhs) {
return (compare(lhs, rhs) & COMPARE_RESULT_GREATER_OR_EQUAL) != 0;
}
};

View File

@@ -1,381 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <stddef.h>
#include <stdint.h> // for uint8_t
#include <ArduinoJson/Memory/MemoryPool.hpp>
#include <ArduinoJson/Misc/Visitable.hpp>
#include <ArduinoJson/Polyfills/type_traits.hpp>
#include <ArduinoJson/Strings/StringAdapters.hpp>
#include <ArduinoJson/Variant/Converter.hpp>
#include <ArduinoJson/Variant/VariantFunctions.hpp>
#include <ArduinoJson/Variant/VariantOperators.hpp>
#include <ArduinoJson/Variant/VariantRef.hpp>
#include <ArduinoJson/Variant/VariantShortcuts.hpp>
#include <ArduinoJson/Variant/VariantTag.hpp>
namespace ARDUINOJSON_NAMESPACE {
// Forward declarations.
class ArrayRef;
class ObjectRef;
// Contains the methods shared by VariantRef and VariantConstRef
template <typename TData>
class VariantRefBase : public VariantTag {
public:
FORCE_INLINE bool isNull() const {
return variantIsNull(_data);
}
FORCE_INLINE bool isUnbound() const {
return !_data;
}
FORCE_INLINE size_t memoryUsage() const {
return _data ? _data->memoryUsage() : 0;
}
FORCE_INLINE size_t nesting() const {
return _data ? _data->nesting() : 0;
}
size_t size() const {
return variantSize(_data);
}
protected:
VariantRefBase(TData *data) : _data(data) {}
TData *_data;
friend TData *getData(const VariantRefBase &variant) {
return variant._data;
}
};
// A variant that can be a any value serializable to a JSON value.
//
// It can be set to:
// - a boolean
// - a char, short, int or a long (signed or unsigned)
// - a string (const char*)
// - a reference to a ArrayRef or ObjectRef
class VariantRef : public VariantRefBase<VariantData>,
public VariantOperators<VariantRef>,
public VariantShortcuts<VariantRef>,
public Visitable {
typedef VariantRefBase<VariantData> base_type;
friend class VariantConstRef;
public:
// Intenal use only
FORCE_INLINE VariantRef(MemoryPool *pool, VariantData *data)
: base_type(data), _pool(pool) {}
// Creates an uninitialized VariantRef
FORCE_INLINE VariantRef() : base_type(0), _pool(0) {}
FORCE_INLINE void clear() const {
return variantSetNull(_data);
}
template <typename T>
FORCE_INLINE bool set(const T &value) const {
Converter<T>::toJson(value, *this);
return _pool && !_pool->overflowed();
}
bool ARDUINOJSON_DEPRECATED(
"Support for char is deprecated, use int8_t or uint8_t instead")
set(char value) const;
template <typename T>
FORCE_INLINE bool set(T *value) const {
Converter<T *>::toJson(value, *this);
return _pool && !_pool->overflowed();
}
template <typename T>
FORCE_INLINE
typename enable_if<!is_same<T, char *>::value && !is_same<T, char>::value,
T>::type
as() const {
return Converter<T>::fromJson(*this);
}
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, char *>::value, const char *>::type
ARDUINOJSON_DEPRECATED("Replace as<char*>() with as<const char*>()")
as() const {
return as<const char *>();
}
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, char>::value, char>::type
ARDUINOJSON_DEPRECATED(
"Support for char is deprecated, use int8_t or uint8_t instead")
as() const {
return static_cast<char>(as<signed char>());
}
template <typename T>
FORCE_INLINE
typename enable_if<!is_same<T, char *>::value && !is_same<T, char>::value,
bool>::type
is() const {
return Converter<T>::checkJson(*this);
}
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, char *>::value, bool>::type
ARDUINOJSON_DEPRECATED("Replace is<char*>() with is<const char*>()")
is() const {
return is<const char *>();
}
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, char>::value, bool>::type
ARDUINOJSON_DEPRECATED(
"Support for char is deprecated, use int8_t or uint8_t instead")
is() const {
return is<signed char>();
}
template <typename T>
FORCE_INLINE operator T() const {
return as<T>();
}
template <typename TVisitor>
typename TVisitor::result_type accept(TVisitor &visitor) const {
return variantAccept(_data, visitor);
}
// Change the type of the variant
//
// ArrayRef to<ArrayRef>()
template <typename T>
typename enable_if<is_same<T, ArrayRef>::value, ArrayRef>::type to() const;
//
// ObjectRef to<ObjectRef>()
template <typename T>
typename enable_if<is_same<T, ObjectRef>::value, ObjectRef>::type to() const;
//
// ObjectRef to<VariantRef>()
template <typename T>
typename enable_if<is_same<T, VariantRef>::value, VariantRef>::type to()
const;
VariantRef addElement() const;
FORCE_INLINE VariantRef getElement(size_t) const;
FORCE_INLINE VariantRef getOrAddElement(size_t) const;
// getMember(const char*) const
// getMember(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef getMember(TChar *) const;
// getMember(const std::string&) const
// getMember(const String&) const
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value, VariantRef>::type
getMember(const TString &) const;
// getOrAddMember(char*) const
// getOrAddMember(const char*) const
// getOrAddMember(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantRef getOrAddMember(TChar *) const;
// getOrAddMember(const std::string&) const
// getOrAddMember(const String&) const
template <typename TString>
FORCE_INLINE VariantRef getOrAddMember(const TString &) const;
FORCE_INLINE void remove(size_t index) const {
if (_data)
_data->remove(index);
}
// remove(char*) const
// remove(const char*) const
// remove(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar *>::value>::type remove(
TChar *key) const {
if (_data)
_data->remove(adaptString(key));
}
// remove(const std::string&) const
// remove(const String&) const
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
const TString &key) const {
if (_data)
_data->remove(adaptString(key));
}
private:
MemoryPool *_pool;
friend MemoryPool *getPool(const VariantRef &variant) {
return variant._pool;
}
};
class VariantConstRef : public VariantRefBase<const VariantData>,
public VariantOperators<VariantConstRef>,
public VariantShortcuts<VariantConstRef>,
public Visitable {
typedef VariantRefBase<const VariantData> base_type;
friend class VariantRef;
public:
VariantConstRef() : base_type(0) {}
VariantConstRef(const VariantData *data) : base_type(data) {}
VariantConstRef(VariantRef var) : base_type(var._data) {}
template <typename TVisitor>
typename TVisitor::result_type accept(TVisitor &visitor) const {
return variantAccept(_data, visitor);
}
template <typename T>
FORCE_INLINE
typename enable_if<!is_same<T, char *>::value && !is_same<T, char>::value,
T>::type
as() const {
return Converter<T>::fromJson(*this);
}
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, char *>::value, const char *>::type
ARDUINOJSON_DEPRECATED("Replace as<char*>() with as<const char*>()")
as() const {
return as<const char *>();
}
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, char>::value, char>::type
ARDUINOJSON_DEPRECATED(
"Support for char is deprecated, use int8_t or uint8_t instead")
as() const {
return static_cast<char>(as<signed char>());
}
template <typename T>
FORCE_INLINE
typename enable_if<!is_same<T, char *>::value && !is_same<T, char>::value,
bool>::type
is() const {
return Converter<T>::checkJson(*this);
}
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, char *>::value, bool>::type
ARDUINOJSON_DEPRECATED("Replace is<char*>() with is<const char*>()")
is() const {
return is<const char *>();
}
template <typename T>
FORCE_INLINE typename enable_if<is_same<T, char>::value, bool>::type
ARDUINOJSON_DEPRECATED(
"Support for char is deprecated, use int8_t or uint8_t instead")
is() const {
return is<signed char>();
}
template <typename T>
FORCE_INLINE operator T() const {
return as<T>();
}
FORCE_INLINE VariantConstRef getElement(size_t) const;
FORCE_INLINE VariantConstRef operator[](size_t index) const {
return getElement(index);
}
// getMember(const std::string&) const
// getMember(const String&) const
template <typename TString>
FORCE_INLINE VariantConstRef getMember(const TString &key) const {
return VariantConstRef(
objectGetMember(variantAsObject(_data), adaptString(key)));
}
// getMember(char*) const
// getMember(const char*) const
// getMember(const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE VariantConstRef getMember(TChar *key) const {
const CollectionData *obj = variantAsObject(_data);
return VariantConstRef(obj ? obj->getMember(adaptString(key)) : 0);
}
// operator[](const std::string&) const
// operator[](const String&) const
template <typename TString>
FORCE_INLINE
typename enable_if<IsString<TString>::value, VariantConstRef>::type
operator[](const TString &key) const {
return getMember(key);
}
// operator[](char*) const
// operator[](const char*) const
// operator[](const __FlashStringHelper*) const
template <typename TChar>
FORCE_INLINE
typename enable_if<IsString<TChar *>::value, VariantConstRef>::type
operator[](TChar *key) const {
return getMember(key);
}
};
template <>
struct Converter<VariantRef> {
static void toJson(VariantRef src, VariantRef dst) {
variantCopyFrom(getData(dst), getData(src), getPool(dst));
}
static VariantRef fromJson(VariantRef src) {
return src;
}
static InvalidConversion<VariantConstRef, VariantRef> fromJson(
VariantConstRef);
static bool checkJson(VariantRef src) {
VariantData *data = getData(src);
return !!data;
}
static bool checkJson(VariantConstRef) {
return false;
}
};
template <>
struct Converter<VariantConstRef> {
static void toJson(VariantConstRef src, VariantRef dst) {
variantCopyFrom(getData(dst), getData(src), getPool(dst));
}
static VariantConstRef fromJson(VariantConstRef src) {
return VariantConstRef(getData(src));
}
static bool checkJson(VariantConstRef src) {
const VariantData *data = getData(src);
return !!data;
}
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -0,0 +1,299 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Configuration.hpp>
#include <ArduinoJson/Variant/Converter.hpp>
#include <ArduinoJson/Variant/JsonVariantConst.hpp>
#include <ArduinoJson/Variant/VariantOperators.hpp>
#include <ArduinoJson/Variant/VariantTo.hpp>
namespace ARDUINOJSON_NAMESPACE {
class JsonVariant;
template <typename>
class ElementProxy;
template <typename, typename>
class MemberProxy;
template <typename TDerived>
class VariantRefBase : public VariantTag {
friend class VariantAttorney;
public:
// Sets the value to null.
// ⚠️ Doesn't release the memory associated with the previous value.
// https://arduinojson.org/v6/api/jsonvariant/clear/
FORCE_INLINE void clear() const {
variantSetNull(getData());
}
// Returns true if the value is null or the reference is unbound.
// https://arduinojson.org/v6/api/jsonvariant/isnull/
FORCE_INLINE bool isNull() const {
return variantIsNull(getData());
}
// Returns true if the reference is unbound.
FORCE_INLINE bool isUnbound() const {
return !getData();
}
// Casts the value to the specified type.
// https://arduinojson.org/v6/api/jsonvariant/as/
template <typename T>
FORCE_INLINE typename enable_if<!is_same<T, char*>::value &&
!is_same<T, char>::value &&
!ConverterNeedsWriteableRef<T>::value,
T>::type
as() const {
return Converter<T>::fromJson(getVariantConst());
}
// Casts the value to the specified type.
// https://arduinojson.org/v6/api/jsonvariant/as/
template <typename T>
FORCE_INLINE typename enable_if<ConverterNeedsWriteableRef<T>::value, T>::type
as() const {
return Converter<T>::fromJson(getVariant());
}
template <typename T>
FORCE_INLINE operator T() const {
return as<T>();
}
// Sets the value to an empty array.
// ⚠️ Doesn't release the memory associated with the previous value.
// https://arduinojson.org/v6/api/jsonvariant/to/
template <typename T>
typename enable_if<is_same<T, JsonArray>::value, JsonArray>::type to() const;
// Sets the value to an empty object.
// ⚠️ Doesn't release the memory associated with the previous value.
// https://arduinojson.org/v6/api/jsonvariant/to/
template <typename T>
typename enable_if<is_same<T, JsonObject>::value, JsonObject>::type to()
const;
// Sets the value to null.
// ⚠️ Doesn't release the memory associated with the previous value.
// https://arduinojson.org/v6/api/jsonvariant/to/
template <typename T>
typename enable_if<is_same<T, JsonVariant>::value, JsonVariant>::type to()
const;
// Returns true if the value is of the specified type.
// https://arduinojson.org/v6/api/jsonvariant/is/
template <typename T>
FORCE_INLINE
typename enable_if<ConverterNeedsWriteableRef<T>::value, bool>::type
is() const {
return Converter<T>::checkJson(getVariant());
}
// Returns true if the value is of the specified type.
// https://arduinojson.org/v6/api/jsonvariant/is/
template <typename T>
FORCE_INLINE typename enable_if<!ConverterNeedsWriteableRef<T>::value &&
!is_same<T, char*>::value &&
!is_same<T, char>::value,
bool>::type
is() const {
return Converter<T>::checkJson(getVariantConst());
}
// Shallow copies the specified value.
// https://arduinojson.org/v6/api/jsonvariant/shallowcopy/
FORCE_INLINE void shallowCopy(JsonVariantConst target) {
VariantData* data = getOrCreateData();
if (!data)
return;
const VariantData* targetData = VariantAttorney::getData(target);
if (targetData)
*data = *targetData;
else
data->setNull();
}
// Copies the specified value.
// https://arduinojson.org/v6/api/jsonvariant/set/
template <typename T>
FORCE_INLINE bool set(const T& value) const {
Converter<T>::toJson(value, getOrCreateVariant());
MemoryPool* pool = getPool();
return pool && !pool->overflowed();
}
// Copies the specified value.
// https://arduinojson.org/v6/api/jsonvariant/set/
template <typename T>
FORCE_INLINE bool set(T* value) const {
Converter<T*>::toJson(value, getOrCreateVariant());
MemoryPool* pool = getPool();
return pool && !pool->overflowed();
}
// Returns the size of the array or object.
// https://arduinojson.org/v6/api/jsonvariant/size/
FORCE_INLINE size_t size() const {
return variantSize(getData());
}
// Returns the number of bytes occupied by the value.
// https://arduinojson.org/v6/api/jsonvariant/memoryusage/
FORCE_INLINE size_t memoryUsage() const {
VariantData* data = getData();
return data ? data->memoryUsage() : 0;
}
// Returns the depth (nesting level) of the value.
// https://arduinojson.org/v6/api/jsonvariant/nesting/
FORCE_INLINE size_t nesting() const {
return variantNesting(getData());
}
// Appends a new (null) element to the array.
// Returns a reference to the new element.
// https://arduinojson.org/v6/api/jsonvariant/add/
FORCE_INLINE JsonVariant add() const;
// Appends a value to the array.
// https://arduinojson.org/v6/api/jsonvariant/add/
template <typename T>
FORCE_INLINE bool add(const T& value) const {
return add().set(value);
}
// Appends a value to the array.
// https://arduinojson.org/v6/api/jsonvariant/add/
template <typename T>
FORCE_INLINE bool add(T* value) const {
return add().set(value);
}
// Removes an element of the array.
// ⚠️ Doesn't release the memory associated with the removed element.
// https://arduinojson.org/v6/api/jsonvariant/remove/
FORCE_INLINE void remove(size_t index) const {
VariantData* data = getData();
if (data)
data->remove(index);
}
// Removes a member of the object.
// ⚠️ Doesn't release the memory associated with the removed element.
// https://arduinojson.org/v6/api/jsonvariant/remove/
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value>::type remove(
TChar* key) const {
VariantData* data = getData();
if (data)
data->remove(adaptString(key));
}
// Removes a member of the object.
// ⚠️ Doesn't release the memory associated with the removed element.
// https://arduinojson.org/v6/api/jsonvariant/remove/
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
const TString& key) const {
VariantData* data = getData();
if (data)
data->remove(adaptString(key));
}
// Creates an array and appends it to the array.
// https://arduinojson.org/v6/api/jsonvariant/createnestedarray/
FORCE_INLINE JsonArray createNestedArray() const;
// Creates an object and appends it to the array.
// https://arduinojson.org/v6/api/jsonvariant/createnestedobject/
FORCE_INLINE JsonObject createNestedObject() const;
// Gets or sets an array element.
// https://arduinojson.org/v6/api/jsonvariant/subscript/
FORCE_INLINE ElementProxy<TDerived> operator[](size_t index) const;
// Returns true if the object contains the specified key.
// https://arduinojson.org/v6/api/jsonvariant/containskey/
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value, bool>::type
containsKey(const TString& key) const;
// Returns true if the object contains the specified key.
// https://arduinojson.org/v6/api/jsonvariant/containskey/
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value, bool>::type
containsKey(TChar* key) const;
// Gets or sets an object member.
// https://arduinojson.org/v6/api/jsonvariant/subscript/
template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value,
MemberProxy<TDerived, TString> >::type
operator[](const TString& key) const;
// Gets or sets an object member.
// https://arduinojson.org/v6/api/jsonvariant/subscript/
template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar*>::value,
MemberProxy<TDerived, TChar*> >::type
operator[](TChar* key) const;
// Creates an array and adds it to the object.
// https://arduinojson.org/v6/api/jsonvariant/createnestedarray/
template <typename TString>
FORCE_INLINE JsonArray createNestedArray(const TString& key) const;
// Creates an array and adds it to the object.
// https://arduinojson.org/v6/api/jsonvariant/createnestedarray/
template <typename TChar>
FORCE_INLINE JsonArray createNestedArray(TChar* key) const;
// Creates an object and adds it to the object.
// https://arduinojson.org/v6/api/jsonvariant/createnestedobject/
template <typename TString>
JsonObject createNestedObject(const TString& key) const;
// Creates an object and adds it to the object.
// https://arduinojson.org/v6/api/jsonvariant/createnestedobject/
template <typename TChar>
JsonObject createNestedObject(TChar* key) const;
private:
TDerived& derived() {
return static_cast<TDerived&>(*this);
}
const TDerived& derived() const {
return static_cast<const TDerived&>(*this);
}
FORCE_INLINE MemoryPool* getPool() const {
return VariantAttorney::getPool(derived());
}
FORCE_INLINE VariantData* getData() const {
return VariantAttorney::getData(derived());
}
FORCE_INLINE VariantData* getOrCreateData() const {
return VariantAttorney::getOrCreateData(derived());
}
private:
FORCE_INLINE JsonVariant getVariant() const;
FORCE_INLINE JsonVariantConst getVariantConst() const {
return JsonVariantConst(getData());
}
FORCE_INLINE JsonVariant getOrCreateVariant() const;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -1,23 +0,0 @@
// ArduinoJson - https://arduinojson.org
// Copyright © 2014-2022, Benoit BLANCHON
// MIT License
#pragma once
#include <ArduinoJson/Array/ArrayShortcuts.hpp>
#include <ArduinoJson/Object/ObjectShortcuts.hpp>
namespace ARDUINOJSON_NAMESPACE {
template <typename TVariant>
class VariantShortcuts : public ObjectShortcuts<TVariant>,
public ArrayShortcuts<TVariant> {
public:
using ArrayShortcuts<TVariant>::createNestedArray;
using ArrayShortcuts<TVariant>::createNestedObject;
using ArrayShortcuts<TVariant>::operator[];
using ObjectShortcuts<TVariant>::createNestedArray;
using ObjectShortcuts<TVariant>::createNestedObject;
using ObjectShortcuts<TVariant>::operator[];
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -76,7 +76,7 @@ class VariantSlot {
_next = VariantSlotDiff(slot - this);
}
void setKey(String k) {
void setKey(JsonString k) {
ARDUINOJSON_ASSERT(k);
if (k.isLinked())
_flags &= VALUE_MASK;

View File

@@ -7,26 +7,26 @@
#include <ArduinoJson/Namespace.hpp>
namespace ARDUINOJSON_NAMESPACE {
class ArrayRef;
class ObjectRef;
class VariantRef;
class JsonArray;
class JsonObject;
class JsonVariant;
// A metafunction that returns the type of the value returned by
// VariantRef::to<T>()
// JsonVariant::to<T>()
template <typename T>
struct VariantTo {};
template <>
struct VariantTo<ArrayRef> {
typedef ArrayRef type;
struct VariantTo<JsonArray> {
typedef JsonArray type;
};
template <>
struct VariantTo<ObjectRef> {
typedef ObjectRef type;
struct VariantTo<JsonObject> {
typedef JsonObject type;
};
template <>
struct VariantTo<VariantRef> {
typedef VariantRef type;
struct VariantTo<JsonVariant> {
typedef JsonVariant type;
};
} // namespace ARDUINOJSON_NAMESPACE

View File

@@ -5,8 +5,8 @@
#pragma once
#include <ArduinoJson/Collection/CollectionData.hpp>
#include <ArduinoJson/Numbers/Float.hpp>
#include <ArduinoJson/Numbers/Integer.hpp>
#include <ArduinoJson/Numbers/JsonFloat.hpp>
#include <ArduinoJson/Numbers/JsonInteger.hpp>
namespace ARDUINOJSON_NAMESPACE {
@@ -14,7 +14,7 @@ template <typename TResult>
struct Visitor {
typedef TResult result_type;
TResult visitArray(const CollectionData &) {
TResult visitArray(const CollectionData&) {
return TResult();
}
@@ -22,11 +22,11 @@ struct Visitor {
return TResult();
}
TResult visitFloat(Float) {
TResult visitFloat(JsonFloat) {
return TResult();
}
TResult visitSignedInteger(Integer) {
TResult visitSignedInteger(JsonInteger) {
return TResult();
}
@@ -34,19 +34,19 @@ struct Visitor {
return TResult();
}
TResult visitObject(const CollectionData &) {
TResult visitObject(const CollectionData&) {
return TResult();
}
TResult visitUnsignedInteger(UInt) {
TResult visitUnsignedInteger(JsonUInt) {
return TResult();
}
TResult visitRawJson(const char *, size_t) {
TResult visitRawJson(const char*, size_t) {
return TResult();
}
TResult visitString(const char *, size_t) {
TResult visitString(const char*, size_t) {
return TResult();
}
};

View File

@@ -4,7 +4,7 @@
#pragma once
#define ARDUINOJSON_VERSION "6.19.4"
#define ARDUINOJSON_VERSION "6.20.0"
#define ARDUINOJSON_VERSION_MAJOR 6
#define ARDUINOJSON_VERSION_MINOR 19
#define ARDUINOJSON_VERSION_REVISION 4
#define ARDUINOJSON_VERSION_MINOR 20
#define ARDUINOJSON_VERSION_REVISION 0