mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-04 06:06:36 +02:00
Compare commits
22 Commits
Author | SHA1 | Date | |
---|---|---|---|
a7e928d126 | |||
591fe7e92b | |||
d6e61cbcda | |||
5825366fe4 | |||
6df204cf40 | |||
3f7e1db549 | |||
a6091136b0 | |||
353bbd0e8c | |||
a428e125fa | |||
2e262b2689 | |||
a2d055e408 | |||
57defe00ee | |||
ac5a2676e7 | |||
ed98ea4e43 | |||
729bf0afd2 | |||
2ea7ea153c | |||
2772e66064 | |||
d41f7a8165 | |||
abfd3997eb | |||
788c9be016 | |||
c3d7a79a83 | |||
1782348275 |
14
.travis.yml
14
.travis.yml
@ -8,12 +8,6 @@ matrix:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.4']
|
||||
env: SCRIPT=cmake GCC=4.4
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-4.5']
|
||||
env: SCRIPT=cmake GCC=4.5
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
@ -50,6 +44,12 @@ matrix:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-6']
|
||||
env: SCRIPT=cmake GCC=6
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test']
|
||||
packages: ['g++-7']
|
||||
env: SCRIPT=cmake GCC=7
|
||||
- compiler: clang
|
||||
env: SCRIPT=cmake
|
||||
- compiler: clang
|
||||
@ -89,9 +89,7 @@ matrix:
|
||||
- env: SCRIPT=arduino VERSION=1.6.7 BOARD=arduino:avr:uno
|
||||
- env: SCRIPT=arduino VERSION=1.8.2 BOARD=arduino:avr:uno
|
||||
- env: SCRIPT=platformio BOARD=uno
|
||||
- env: SCRIPT=platformio BOARD=due
|
||||
- env: SCRIPT=platformio BOARD=esp01
|
||||
#- env: SCRIPT=platformio BOARD=teensy31C
|
||||
cache:
|
||||
directories:
|
||||
- "~/.platformio"
|
||||
|
16
CHANGELOG.md
16
CHANGELOG.md
@ -1,6 +1,22 @@
|
||||
ArduinoJson: change log
|
||||
=======================
|
||||
|
||||
v5.11.2
|
||||
-------
|
||||
|
||||
* Fixed `DynamicJsonBuffer::clear()` not resetting allocation size (issue #561)
|
||||
* Fixed incorrect rounding for float values (issue #588)
|
||||
|
||||
v5.11.1
|
||||
-------
|
||||
|
||||
* Removed dependency on `PGM_P` as Particle 0.6.2 doesn't define it (issue #546)
|
||||
* Fixed warning "dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]"
|
||||
* Fixed warning "floating constant exceeds range of 'float' [-Woverflow]" (issue #544)
|
||||
* Fixed warning "this statement may fall through" [-Wimplicit-fallthrough=] (issue #539)
|
||||
* Removed `ARDUINOJSON_DOUBLE_IS_64BITS` as it became useless.
|
||||
* Fixed too many decimals places in float serialization (issue #543)
|
||||
|
||||
v5.11.0
|
||||
-------
|
||||
|
||||
|
11
CONTRIBUTING.md
Normal file
11
CONTRIBUTING.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Contribution to ArduinoJson
|
||||
|
||||
First, thank you for taking the time to contribute to this project.
|
||||
|
||||
You can submit changes via GitHub Pull Requests.
|
||||
|
||||
Please:
|
||||
|
||||
1. Unit test every change in behavior
|
||||
2. Use clang-format in "file" mode to format the code
|
||||
3. Consider using the Continuous Integration (Travis and AppVeyor)
|
@ -1,8 +1,10 @@
|
||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/master) [](https://travis-ci.org/bblanchon/ArduinoJson) [](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master) [](https://github.com/bblanchon/ArduinoJson)
|
||||
|
||||

|
||||
|
||||
ArduinoJson - C++ JSON library for IoT
|
||||
====================
|
||||
|
||||
[](https://ci.appveyor.com/project/bblanchon/arduinojson/branch/master) [](https://travis-ci.org/bblanchon/ArduinoJson) [](https://coveralls.io/r/bblanchon/ArduinoJson?branch=master) [](https://github.com/bblanchon/ArduinoJson)
|
||||
|
||||
*An elegant and efficient JSON library for embedded systems.*
|
||||
|
||||
It's designed to have the most intuitive API, the smallest footprint and is able to work without any allocation on the heap (no malloc).
|
||||
@ -118,6 +120,9 @@ Special thanks to the following persons and companies who made generous donation
|
||||
* Prokhoryatov Alexey <img alt='Russia' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f7-1f1fa.svg' width='18' height='18'>
|
||||
* Google Inc. <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Charles Haynes <img alt='Australia' src='https://d1j8pt39hxlh3d.cloudfront.net/development/emojione/2.2/989/2546.svg' width='18' height='18'>
|
||||
* Charles Walker <img alt='USA' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1fa-1f1f8.svg' width='18' height='18'>
|
||||
* Günther Jehle <img alt='Liechtenstein' src='https://cdnjs.cloudflare.com/ajax/libs/emojione/2.1.4/assets/svg/1f1f1-1f1ee.svg' width='18' height='18'>
|
||||
* Patrick Elliott
|
||||
|
||||
|
||||
---
|
||||
|
27
SUPPORT.md
Normal file
27
SUPPORT.md
Normal file
@ -0,0 +1,27 @@
|
||||
# ArduinoJson Support
|
||||
|
||||
First off, thank you very much for using ArduinoJson.
|
||||
|
||||
We'll be very happy to help you, but first please read the following.
|
||||
|
||||
## Before asking for help
|
||||
|
||||
1. Read the [FAQ](https://bblanchon.github.io/ArduinoJson/faq/)
|
||||
2. Search in the [API Reference](https://bblanchon.github.io/ArduinoJson/api/)
|
||||
|
||||
If you did not find the answer, please create a [new issue on GitHub](https://github.com/bblanchon/ArduinoJson/issues/new).
|
||||
|
||||
It is OK to add a comment to a currently opened issue, but please avoid adding comments to a closed issue.
|
||||
|
||||
## Before hitting the Submit button
|
||||
|
||||
Please provide all the relevant information:
|
||||
|
||||
* Good title
|
||||
* Short description of the problem
|
||||
* Target platform
|
||||
* Compiler model and version
|
||||
* [MVCE](https://stackoverflow.com/help/mcve)
|
||||
* Compiler output
|
||||
|
||||
Good questions get fast answers!
|
@ -1,4 +1,4 @@
|
||||
version: 5.11.0.{build}
|
||||
version: 5.11.2.{build}
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
|
367
banner.svg
Normal file
367
banner.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 32 KiB |
@ -6,7 +6,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/bblanchon/ArduinoJson.git"
|
||||
},
|
||||
"version": "5.11.0",
|
||||
"version": "5.11.2",
|
||||
"authors": {
|
||||
"name": "Benoit Blanchon",
|
||||
"url": "https://blog.benoitblanchon.fr"
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=ArduinoJson
|
||||
version=5.11.0
|
||||
version=5.11.2
|
||||
author=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
maintainer=Benoit Blanchon <blog.benoitblanchon.fr>
|
||||
sentence=An efficient and elegant JSON library for Arduino.
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "ArduinoJson/DynamicJsonBuffer.hpp"
|
||||
#include "ArduinoJson/JsonArray.hpp"
|
||||
#include "ArduinoJson/JsonObject.hpp"
|
||||
#include "ArduinoJson/JsonVariantComparisons.hpp"
|
||||
#include "ArduinoJson/StaticJsonBuffer.hpp"
|
||||
|
||||
#include "ArduinoJson/Deserialization/JsonParserImpl.hpp"
|
||||
|
@ -148,16 +148,6 @@
|
||||
#define ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD 1e-5
|
||||
#endif
|
||||
|
||||
// how many bits in a double
|
||||
#ifndef ARDUINOJSON_DOUBLE_IS_64BITS
|
||||
#if /*GCC*/ (defined(__SIZEOF_DOUBLE__) && __SIZEOF_DOUBLE__ < 8) || \
|
||||
/*IAR*/ (defined(__DOUBLE__) && __DOUBLE__ < 64)
|
||||
#define ARDUINOJSON_DOUBLE_IS_64BITS 0
|
||||
#else
|
||||
#define ARDUINOJSON_DOUBLE_IS_64BITS 1 // by default support 64-bit
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_USE_LONG_LONG && ARDUINOJSON_USE_INT64
|
||||
#error ARDUINOJSON_USE_LONG_LONG and ARDUINOJSON_USE_INT64 cannot be set together
|
||||
#endif
|
||||
|
@ -1,69 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../JsonVariantBase.hpp"
|
||||
#include "../StringTraits/StringTraits.hpp"
|
||||
#include "../TypeTraits/EnableIf.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
template <typename TComparand, typename Enable = void>
|
||||
struct JsonVariantComparer {};
|
||||
|
||||
template <typename TString>
|
||||
struct JsonVariantComparer<
|
||||
TString,
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsString<TString>::value>::type> {
|
||||
template <typename TVariant>
|
||||
static bool equals(const JsonVariantBase<TVariant> &variant,
|
||||
const TString &comparand) {
|
||||
const char *value = variant.template as<const char *>();
|
||||
return Internals::StringTraits<TString>::equals(comparand, value);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TComparand>
|
||||
struct JsonVariantComparer<
|
||||
TComparand, typename TypeTraits::EnableIf<
|
||||
!TypeTraits::IsVariant<TComparand>::value &&
|
||||
!TypeTraits::IsString<TComparand>::value>::type> {
|
||||
template <typename TVariant>
|
||||
static bool equals(const JsonVariantBase<TVariant> &variant,
|
||||
const TComparand &comparand) {
|
||||
return variant.template as<TComparand>() == comparand;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename TVariant2>
|
||||
struct JsonVariantComparer<TVariant2,
|
||||
typename TypeTraits::EnableIf<
|
||||
TypeTraits::IsVariant<TVariant2>::value>::type> {
|
||||
template <typename TVariant1>
|
||||
static bool equals(const JsonVariantBase<TVariant1> &left,
|
||||
const TVariant2 &right) {
|
||||
if (left.template is<bool>() && right.template is<bool>())
|
||||
return left.template as<bool>() == right.template as<bool>();
|
||||
if (left.template is<JsonInteger>() && right.template is<JsonInteger>())
|
||||
return left.template as<JsonInteger>() ==
|
||||
right.template as<JsonInteger>();
|
||||
if (left.template is<JsonFloat>() && right.template is<JsonFloat>())
|
||||
return left.template as<JsonFloat>() == right.template as<JsonFloat>();
|
||||
if (left.template is<JsonArray>() && right.template is<JsonArray>())
|
||||
return left.template as<JsonArray>() == right.template as<JsonArray>();
|
||||
if (left.template is<JsonObject>() && right.template is<JsonObject>())
|
||||
return left.template as<JsonObject>() == right.template as<JsonObject>();
|
||||
if (left.template is<char *>() && right.template is<char *>())
|
||||
return strcmp(left.template as<char *>(), right.template as<char *>()) ==
|
||||
0;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -52,7 +52,7 @@ class DynamicJsonBufferBase
|
||||
: _head(NULL), _nextBlockCapacity(initialSize) {}
|
||||
|
||||
~DynamicJsonBufferBase() {
|
||||
freeAllBlocks();
|
||||
clear();
|
||||
}
|
||||
|
||||
// Gets the number of bytes occupied in the buffer
|
||||
@ -71,7 +71,13 @@ class DynamicJsonBufferBase
|
||||
// Resets the buffer.
|
||||
// USE WITH CAUTION: this invalidates all previously allocated data
|
||||
void clear() {
|
||||
freeAllBlocks();
|
||||
Block* currentBlock = _head;
|
||||
while (currentBlock != NULL) {
|
||||
_nextBlockCapacity = currentBlock->capacity;
|
||||
Block* nextBlock = currentBlock->next;
|
||||
_allocator.deallocate(currentBlock);
|
||||
currentBlock = nextBlock;
|
||||
}
|
||||
_head = 0;
|
||||
}
|
||||
|
||||
@ -144,16 +150,6 @@ class DynamicJsonBufferBase
|
||||
return true;
|
||||
}
|
||||
|
||||
void freeAllBlocks() {
|
||||
Block* currentBlock = _head;
|
||||
|
||||
while (currentBlock != NULL) {
|
||||
Block* nextBlock = currentBlock->next;
|
||||
_allocator.deallocate(currentBlock);
|
||||
currentBlock = nextBlock;
|
||||
}
|
||||
}
|
||||
|
||||
TAllocator _allocator;
|
||||
Block* _head;
|
||||
size_t _nextBlockCapacity;
|
||||
|
@ -106,15 +106,16 @@ inline const JsonArraySubscript JsonArray::operator[](size_t index) const {
|
||||
return JsonArraySubscript(*const_cast<JsonArray*>(this), index);
|
||||
}
|
||||
|
||||
template <typename TImplem>
|
||||
inline JsonArraySubscript JsonVariantBase<TImplem>::operator[](size_t index) {
|
||||
return as<JsonArray>()[index];
|
||||
template <typename TImpl>
|
||||
inline JsonArraySubscript JsonVariantSubscripts<TImpl>::operator[](
|
||||
size_t index) {
|
||||
return impl()->template as<JsonArray>()[index];
|
||||
}
|
||||
|
||||
template <typename TImplem>
|
||||
inline const JsonArraySubscript JsonVariantBase<TImplem>::operator[](
|
||||
template <typename TImpl>
|
||||
inline const JsonArraySubscript JsonVariantSubscripts<TImpl>::operator[](
|
||||
size_t index) const {
|
||||
return as<JsonArray>()[index];
|
||||
return impl()->template as<JsonArray>()[index];
|
||||
}
|
||||
|
||||
} // namespace ArduinoJson
|
||||
|
@ -16,16 +16,6 @@
|
||||
#include "TypeTraits/EnableIf.hpp"
|
||||
#include "TypeTraits/IsArray.hpp"
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#elif defined(__GNUC__)
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
#pragma GCC diagnostic push
|
||||
#endif
|
||||
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
class JsonArray;
|
||||
class JsonObject;
|
||||
@ -37,11 +27,6 @@ class JsonObject;
|
||||
// fixed memory allocation.
|
||||
class JsonBuffer : Internals::NonCopyable {
|
||||
public:
|
||||
// CAUTION: NO VIRTUAL DESTRUCTOR!
|
||||
// If we add a virtual constructor the Arduino compiler will add malloc() and
|
||||
// free() to the binary, adding 706 useless bytes.
|
||||
// virtual ~JsonBuffer() {}
|
||||
|
||||
// Allocates an empty JsonArray.
|
||||
//
|
||||
// Returns a reference to the new JsonArray or JsonArray::invalid() if the
|
||||
@ -77,6 +62,11 @@ class JsonBuffer : Internals::NonCopyable {
|
||||
virtual void *alloc(size_t size) = 0;
|
||||
|
||||
protected:
|
||||
// CAUTION: NO VIRTUAL DESTRUCTOR!
|
||||
// If we add a virtual constructor the Arduino compiler will add malloc()
|
||||
// and free() to the binary, adding 706 useless bytes.
|
||||
~JsonBuffer() {}
|
||||
|
||||
// Preserve aligment if necessary
|
||||
static FORCE_INLINE size_t round_size_up(size_t bytes) {
|
||||
#if ARDUINOJSON_ENABLE_ALIGNMENT
|
||||
@ -88,11 +78,3 @@ class JsonBuffer : Internals::NonCopyable {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
@ -9,16 +9,6 @@
|
||||
|
||||
#include "Deserialization/JsonParser.hpp"
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#elif defined(__GNUC__)
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
#pragma GCC diagnostic push
|
||||
#endif
|
||||
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
template <typename TDerived>
|
||||
class JsonBufferBase : public JsonBuffer {
|
||||
@ -127,17 +117,12 @@ class JsonBufferBase : public JsonBuffer {
|
||||
return Internals::makeParser(that(), json, nestingLimit).parseVariant();
|
||||
}
|
||||
|
||||
protected:
|
||||
~JsonBufferBase() {}
|
||||
|
||||
private:
|
||||
TDerived *that() {
|
||||
return static_cast<TDerived *>(this);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
@ -7,133 +7,17 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/JsonVariantAs.hpp"
|
||||
#include "Polyfills/attributes.hpp"
|
||||
#include "JsonVariantCasts.hpp"
|
||||
#include "JsonVariantComparisons.hpp"
|
||||
#include "JsonVariantSubscripts.hpp"
|
||||
#include "Serialization/JsonPrintable.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations.
|
||||
class JsonArraySubscript;
|
||||
template <typename TKey>
|
||||
class JsonObjectSubscript;
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
|
||||
public:
|
||||
#if ARDUINOJSON_ENABLE_DEPRECATED
|
||||
DEPRECATED("use as<JsonArray>() instead")
|
||||
FORCE_INLINE JsonArray &asArray() const {
|
||||
return as<JsonArray>();
|
||||
}
|
||||
|
||||
DEPRECATED("use as<JsonObject>() instead")
|
||||
FORCE_INLINE JsonObject &asObject() const {
|
||||
return as<JsonObject>();
|
||||
}
|
||||
|
||||
DEPRECATED("use as<char*>() instead")
|
||||
FORCE_INLINE const char *asString() const {
|
||||
return as<const char *>();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Gets the variant as an array.
|
||||
// Returns a reference to the JsonArray or JsonArray::invalid() if the
|
||||
// variant
|
||||
// is not an array.
|
||||
FORCE_INLINE operator JsonArray &() const {
|
||||
return as<JsonArray &>();
|
||||
}
|
||||
|
||||
// Gets the variant as an object.
|
||||
// Returns a reference to the JsonObject or JsonObject::invalid() if the
|
||||
// variant is not an object.
|
||||
FORCE_INLINE operator JsonObject &() const {
|
||||
return as<JsonObject &>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE operator T() const {
|
||||
return as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE const typename Internals::JsonVariantAs<T>::type as() const {
|
||||
return impl()->template as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE bool is() const {
|
||||
return impl()->template is<T>();
|
||||
}
|
||||
|
||||
// Mimics an array or an object.
|
||||
// Returns the size of the array or object if the variant has that type.
|
||||
// Returns 0 if the variant is neither an array nor an object
|
||||
size_t size() const {
|
||||
return as<JsonArray>().size() + as<JsonObject>().size();
|
||||
}
|
||||
|
||||
// Mimics an array.
|
||||
// Returns the element at specified index if the variant is an array.
|
||||
// Returns JsonVariant::invalid() if the variant is not an array.
|
||||
FORCE_INLINE const JsonArraySubscript operator[](size_t index) const;
|
||||
FORCE_INLINE JsonArraySubscript operator[](size_t index);
|
||||
|
||||
// Mimics an object.
|
||||
// Returns the value associated with the specified key if the variant is
|
||||
// an object.
|
||||
// Return JsonVariant::invalid() if the variant is not an object.
|
||||
//
|
||||
// const JsonObjectSubscript operator[](TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename TypeTraits::EnableIf<
|
||||
Internals::StringTraits<TString>::has_equals,
|
||||
const JsonObjectSubscript<const TString &> >::type
|
||||
operator[](const TString &key) const {
|
||||
return as<JsonObject>()[key];
|
||||
}
|
||||
//
|
||||
// const JsonObjectSubscript operator[](TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename TypeTraits::EnableIf<
|
||||
Internals::StringTraits<TString>::has_equals,
|
||||
JsonObjectSubscript<const TString &> >::type
|
||||
operator[](const TString &key) {
|
||||
return as<JsonObject>()[key];
|
||||
}
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey);
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename TypeTraits::EnableIf<
|
||||
Internals::StringTraits<const TString *>::has_equals,
|
||||
JsonObjectSubscript<const TString *> >::type
|
||||
operator[](const TString *key) {
|
||||
return as<JsonObject>()[key];
|
||||
}
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey);
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename TypeTraits::EnableIf<
|
||||
Internals::StringTraits<TString *>::has_equals,
|
||||
const JsonObjectSubscript<const TString *> >::type
|
||||
operator[](const TString *key) const {
|
||||
return as<JsonObject>()[key];
|
||||
}
|
||||
|
||||
private:
|
||||
const TImpl *impl() const {
|
||||
return static_cast<const TImpl *>(this);
|
||||
}
|
||||
};
|
||||
|
||||
namespace TypeTraits {
|
||||
template <typename T>
|
||||
struct IsVariant : IsBaseOf<JsonVariantBase<T>, T> {};
|
||||
}
|
||||
class JsonVariantBase : public Internals::JsonPrintable<TImpl>,
|
||||
public JsonVariantCasts<TImpl>,
|
||||
public JsonVariantComparisons<TImpl>,
|
||||
public JsonVariantSubscripts<TImpl>,
|
||||
public TypeTraits::JsonVariantTag {};
|
||||
}
|
||||
|
60
src/ArduinoJson/JsonVariantCasts.hpp
Normal file
60
src/ArduinoJson/JsonVariantCasts.hpp
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/JsonVariantAs.hpp"
|
||||
#include "Polyfills/attributes.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantCasts {
|
||||
public:
|
||||
#if ARDUINOJSON_ENABLE_DEPRECATED
|
||||
DEPRECATED("use as<JsonArray>() instead")
|
||||
FORCE_INLINE JsonArray &asArray() const {
|
||||
return impl()->template as<JsonArray>();
|
||||
}
|
||||
|
||||
DEPRECATED("use as<JsonObject>() instead")
|
||||
FORCE_INLINE JsonObject &asObject() const {
|
||||
return impl()->template as<JsonObject>();
|
||||
}
|
||||
|
||||
DEPRECATED("use as<char*>() instead")
|
||||
FORCE_INLINE const char *asString() const {
|
||||
return impl()->template as<const char *>();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Gets the variant as an array.
|
||||
// Returns a reference to the JsonArray or JsonArray::invalid() if the
|
||||
// variant
|
||||
// is not an array.
|
||||
FORCE_INLINE operator JsonArray &() const {
|
||||
return impl()->template as<JsonArray &>();
|
||||
}
|
||||
|
||||
// Gets the variant as an object.
|
||||
// Returns a reference to the JsonObject or JsonObject::invalid() if the
|
||||
// variant is not an object.
|
||||
FORCE_INLINE operator JsonObject &() const {
|
||||
return impl()->template as<JsonObject &>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
FORCE_INLINE operator T() const {
|
||||
return impl()->template as<T>();
|
||||
}
|
||||
|
||||
private:
|
||||
const TImpl *impl() const {
|
||||
return static_cast<const TImpl *>(this);
|
||||
}
|
||||
};
|
||||
}
|
@ -7,82 +7,138 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/JsonVariantComparer.hpp"
|
||||
#include "StringTraits/StringTraits.hpp"
|
||||
#include "TypeTraits/EnableIf.hpp"
|
||||
#include "TypeTraits/IsVariant.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
template <typename TVariant, typename TComparand>
|
||||
inline bool operator==(const JsonVariantBase<TVariant> &variant,
|
||||
TComparand comparand) {
|
||||
return Internals::JsonVariantComparer<TComparand>::equals(variant, comparand);
|
||||
}
|
||||
|
||||
template <typename TVariant, typename TComparand>
|
||||
inline typename TypeTraits::EnableIf<!TypeTraits::IsVariant<TComparand>::value,
|
||||
bool>::type
|
||||
operator==(TComparand comparand, const JsonVariantBase<TVariant> &variant) {
|
||||
return Internals::JsonVariantComparer<TComparand>::equals(variant, comparand);
|
||||
}
|
||||
template <typename TImpl>
|
||||
class JsonVariantComparisons {
|
||||
public:
|
||||
template <typename TComparand>
|
||||
friend bool operator==(const JsonVariantComparisons &variant,
|
||||
TComparand comparand) {
|
||||
return variant.equals(comparand);
|
||||
}
|
||||
|
||||
template <typename TVariant, typename TComparand>
|
||||
inline bool operator!=(const JsonVariantBase<TVariant> &variant,
|
||||
TComparand comparand) {
|
||||
return !Internals::JsonVariantComparer<TComparand>::equals(variant,
|
||||
comparand);
|
||||
}
|
||||
template <typename TComparand>
|
||||
friend
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsVariant<TComparand>::value,
|
||||
bool>::type
|
||||
operator==(TComparand comparand, const JsonVariantComparisons &variant) {
|
||||
return variant.equals(comparand);
|
||||
}
|
||||
|
||||
template <typename TVariant, typename TComparand>
|
||||
inline typename TypeTraits::EnableIf<!TypeTraits::IsVariant<TComparand>::value,
|
||||
bool>::type
|
||||
operator!=(TComparand comparand, const JsonVariantBase<TVariant> &variant) {
|
||||
return !Internals::JsonVariantComparer<TComparand>::equals(variant,
|
||||
comparand);
|
||||
}
|
||||
template <typename TComparand>
|
||||
friend bool operator!=(const JsonVariantComparisons &variant,
|
||||
TComparand comparand) {
|
||||
return !variant.equals(comparand);
|
||||
}
|
||||
|
||||
template <typename TVariant, typename TComparand>
|
||||
inline bool operator<=(const JsonVariantBase<TVariant> &left,
|
||||
TComparand right) {
|
||||
return left.template as<TComparand>() <= right;
|
||||
}
|
||||
template <typename TComparand>
|
||||
friend
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsVariant<TComparand>::value,
|
||||
bool>::type
|
||||
operator!=(TComparand comparand, const JsonVariantComparisons &variant) {
|
||||
return !variant.equals(comparand);
|
||||
}
|
||||
|
||||
template <typename TVariant, typename TComparand>
|
||||
inline bool operator<=(TComparand comparand,
|
||||
const JsonVariantBase<TVariant> &variant) {
|
||||
return comparand <= variant.template as<TComparand>();
|
||||
}
|
||||
template <typename TComparand>
|
||||
friend bool operator<=(const JsonVariantComparisons &left, TComparand right) {
|
||||
return left.as<TComparand>() <= right;
|
||||
}
|
||||
|
||||
template <typename TVariant, typename TComparand>
|
||||
inline bool operator>=(const JsonVariantBase<TVariant> &variant,
|
||||
TComparand comparand) {
|
||||
return variant.template as<TComparand>() >= comparand;
|
||||
}
|
||||
template <typename TComparand>
|
||||
friend bool operator<=(TComparand comparand,
|
||||
const JsonVariantComparisons &variant) {
|
||||
return comparand <= variant.as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TVariant, typename TComparand>
|
||||
inline bool operator>=(TComparand comparand,
|
||||
const JsonVariantBase<TVariant> &variant) {
|
||||
return comparand >= variant.template as<TComparand>();
|
||||
}
|
||||
template <typename TComparand>
|
||||
friend bool operator>=(const JsonVariantComparisons &variant,
|
||||
TComparand comparand) {
|
||||
return variant.as<TComparand>() >= comparand;
|
||||
}
|
||||
|
||||
template <typename TVariant, typename TComparand>
|
||||
inline bool operator<(const JsonVariantBase<TVariant> &varian,
|
||||
TComparand comparand) {
|
||||
return varian.template as<TComparand>() < comparand;
|
||||
}
|
||||
template <typename TComparand>
|
||||
friend bool operator>=(TComparand comparand,
|
||||
const JsonVariantComparisons &variant) {
|
||||
return comparand >= variant.as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TVariant, typename TComparand>
|
||||
inline bool operator<(TComparand comparand,
|
||||
const JsonVariantBase<TVariant> &variant) {
|
||||
return comparand < variant.template as<TComparand>();
|
||||
}
|
||||
template <typename TComparand>
|
||||
friend bool operator<(const JsonVariantComparisons &varian,
|
||||
TComparand comparand) {
|
||||
return varian.as<TComparand>() < comparand;
|
||||
}
|
||||
|
||||
template <typename TVariant, typename TComparand>
|
||||
inline bool operator>(const JsonVariantBase<TVariant> &variant,
|
||||
TComparand comparand) {
|
||||
return variant.template as<TComparand>() > comparand;
|
||||
}
|
||||
template <typename TComparand>
|
||||
friend bool operator<(TComparand comparand,
|
||||
const JsonVariantComparisons &variant) {
|
||||
return comparand < variant.as<TComparand>();
|
||||
}
|
||||
|
||||
template <typename TVariant, typename TComparand>
|
||||
inline bool operator>(TComparand comparand,
|
||||
const JsonVariantBase<TVariant> &variant) {
|
||||
return comparand > variant.template as<TComparand>();
|
||||
}
|
||||
template <typename TComparand>
|
||||
friend bool operator>(const JsonVariantComparisons &variant,
|
||||
TComparand comparand) {
|
||||
return variant.as<TComparand>() > comparand;
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
friend bool operator>(TComparand comparand,
|
||||
const JsonVariantComparisons &variant) {
|
||||
return comparand > variant.as<TComparand>();
|
||||
}
|
||||
|
||||
private:
|
||||
const TImpl *impl() const {
|
||||
return static_cast<const TImpl *>(this);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const typename Internals::JsonVariantAs<T>::type as() const {
|
||||
return impl()->template as<T>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool is() const {
|
||||
return impl()->template is<T>();
|
||||
}
|
||||
|
||||
template <typename TString>
|
||||
typename TypeTraits::EnableIf<TypeTraits::IsString<TString>::value,
|
||||
bool>::type
|
||||
equals(const TString &comparand) const {
|
||||
const char *value = as<const char *>();
|
||||
return Internals::StringTraits<TString>::equals(comparand, value);
|
||||
}
|
||||
|
||||
template <typename TComparand>
|
||||
typename TypeTraits::EnableIf<!TypeTraits::IsVariant<TComparand>::value &&
|
||||
!TypeTraits::IsString<TComparand>::value,
|
||||
bool>::type
|
||||
equals(const TComparand &comparand) const {
|
||||
return as<TComparand>() == comparand;
|
||||
}
|
||||
|
||||
template <typename TVariant2>
|
||||
bool equals(const JsonVariantComparisons<TVariant2> &right) const {
|
||||
using namespace Internals;
|
||||
if (is<bool>() && right.template is<bool>())
|
||||
return as<bool>() == right.template as<bool>();
|
||||
if (is<JsonInteger>() && right.template is<JsonInteger>())
|
||||
return as<JsonInteger>() == right.template as<JsonInteger>();
|
||||
if (is<JsonFloat>() && right.template is<JsonFloat>())
|
||||
return as<JsonFloat>() == right.template as<JsonFloat>();
|
||||
if (is<JsonArray>() && right.template is<JsonArray>())
|
||||
return as<JsonArray>() == right.template as<JsonArray>();
|
||||
if (is<JsonObject>() && right.template is<JsonObject>())
|
||||
return as<JsonObject>() == right.template as<JsonObject>();
|
||||
if (is<char *>() && right.template is<char *>())
|
||||
return strcmp(as<char *>(), right.template as<char *>()) == 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
89
src/ArduinoJson/JsonVariantSubscripts.hpp
Normal file
89
src/ArduinoJson/JsonVariantSubscripts.hpp
Normal file
@ -0,0 +1,89 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Data/JsonVariantAs.hpp"
|
||||
#include "Polyfills/attributes.hpp"
|
||||
#include "StringTraits/StringTraits.hpp"
|
||||
#include "TypeTraits/EnableIf.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
// Forward declarations.
|
||||
class JsonArraySubscript;
|
||||
template <typename TKey>
|
||||
class JsonObjectSubscript;
|
||||
|
||||
template <typename TImpl>
|
||||
class JsonVariantSubscripts {
|
||||
public:
|
||||
// Mimics an array or an object.
|
||||
// Returns the size of the array or object if the variant has that type.
|
||||
// Returns 0 if the variant is neither an array nor an object
|
||||
size_t size() const {
|
||||
return impl()->template as<JsonArray>().size() +
|
||||
impl()->template as<JsonObject>().size();
|
||||
}
|
||||
|
||||
// Mimics an array.
|
||||
// Returns the element at specified index if the variant is an array.
|
||||
// Returns JsonVariant::invalid() if the variant is not an array.
|
||||
FORCE_INLINE const JsonArraySubscript operator[](size_t index) const;
|
||||
FORCE_INLINE JsonArraySubscript operator[](size_t index);
|
||||
|
||||
// Mimics an object.
|
||||
// Returns the value associated with the specified key if the variant is
|
||||
// an object.
|
||||
// Return JsonVariant::invalid() if the variant is not an object.
|
||||
//
|
||||
// const JsonObjectSubscript operator[](TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename TypeTraits::EnableIf<
|
||||
Internals::StringTraits<TString>::has_equals,
|
||||
const JsonObjectSubscript<const TString &> >::type
|
||||
operator[](const TString &key) const {
|
||||
return impl()->template as<JsonObject>()[key];
|
||||
}
|
||||
//
|
||||
// const JsonObjectSubscript operator[](TKey) const;
|
||||
// TKey = const std::string&, const String&
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename TypeTraits::EnableIf<
|
||||
Internals::StringTraits<TString>::has_equals,
|
||||
JsonObjectSubscript<const TString &> >::type
|
||||
operator[](const TString &key) {
|
||||
return impl()->template as<JsonObject>()[key];
|
||||
}
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey);
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename TypeTraits::EnableIf<
|
||||
Internals::StringTraits<const TString *>::has_equals,
|
||||
JsonObjectSubscript<const TString *> >::type
|
||||
operator[](const TString *key) {
|
||||
return impl()->template as<JsonObject>()[key];
|
||||
}
|
||||
//
|
||||
// JsonObjectSubscript operator[](TKey);
|
||||
// TKey = const char*, const char[N], const FlashStringHelper*
|
||||
template <typename TString>
|
||||
FORCE_INLINE typename TypeTraits::EnableIf<
|
||||
Internals::StringTraits<TString *>::has_equals,
|
||||
const JsonObjectSubscript<const TString *> >::type
|
||||
operator[](const TString *key) const {
|
||||
return impl()->template as<JsonObject>()[key];
|
||||
}
|
||||
|
||||
private:
|
||||
const TImpl *impl() const {
|
||||
return static_cast<const TImpl *>(this);
|
||||
}
|
||||
};
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Polyfills {
|
||||
template <typename T>
|
||||
int16_t normalize(T& value) {
|
||||
int16_t powersOf10 = 0;
|
||||
|
||||
if (value >= ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD) {
|
||||
#if ARDUINOJSON_DOUBLE_IS_64BITS
|
||||
if (value >= 1e256) {
|
||||
value /= 1e256;
|
||||
powersOf10 = int16_t(powersOf10 + 256);
|
||||
}
|
||||
if (value >= 1e128) {
|
||||
value /= 1e128;
|
||||
powersOf10 = int16_t(powersOf10 + 128);
|
||||
}
|
||||
if (value >= 1e64) {
|
||||
value /= 1e64;
|
||||
powersOf10 = int16_t(powersOf10 + 64);
|
||||
}
|
||||
#endif
|
||||
if (value >= 1e32) {
|
||||
value /= 1e32;
|
||||
powersOf10 = int16_t(powersOf10 + 32);
|
||||
}
|
||||
if (value >= 1e16) {
|
||||
value /= 1e16;
|
||||
powersOf10 = int16_t(powersOf10 + 16);
|
||||
}
|
||||
if (value >= 1e8) {
|
||||
value /= 1e8;
|
||||
powersOf10 = int16_t(powersOf10 + 8);
|
||||
}
|
||||
if (value >= 1e4) {
|
||||
value /= 1e4;
|
||||
powersOf10 = int16_t(powersOf10 + 4);
|
||||
}
|
||||
if (value >= 1e2) {
|
||||
value /= 1e2;
|
||||
powersOf10 = int16_t(powersOf10 + 2);
|
||||
}
|
||||
if (value >= 1e1) {
|
||||
value /= 1e1;
|
||||
powersOf10 = int16_t(powersOf10 + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (value > 0 && value <= ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD) {
|
||||
#if ARDUINOJSON_DOUBLE_IS_64BITS
|
||||
if (value < 1e-255) {
|
||||
value *= 1e256;
|
||||
powersOf10 = int16_t(powersOf10 - 256);
|
||||
}
|
||||
if (value < 1e-127) {
|
||||
value *= 1e128;
|
||||
powersOf10 = int16_t(powersOf10 - 128);
|
||||
}
|
||||
if (value < 1e-63) {
|
||||
value *= 1e64;
|
||||
powersOf10 = int16_t(powersOf10 - 64);
|
||||
}
|
||||
#endif
|
||||
if (value < 1e-31) {
|
||||
value *= 1e32;
|
||||
powersOf10 = int16_t(powersOf10 - 32);
|
||||
}
|
||||
if (value < 1e-15) {
|
||||
value *= 1e16;
|
||||
powersOf10 = int16_t(powersOf10 - 16);
|
||||
}
|
||||
if (value < 1e-7) {
|
||||
value *= 1e8;
|
||||
powersOf10 = int16_t(powersOf10 - 8);
|
||||
}
|
||||
if (value < 1e-3) {
|
||||
value *= 1e4;
|
||||
powersOf10 = int16_t(powersOf10 - 4);
|
||||
}
|
||||
if (value < 1e-1) {
|
||||
value *= 1e2;
|
||||
powersOf10 = int16_t(powersOf10 - 2);
|
||||
}
|
||||
if (value < 1e0) {
|
||||
value *= 1e1;
|
||||
powersOf10 = int16_t(powersOf10 - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return powersOf10;
|
||||
}
|
||||
}
|
||||
}
|
@ -26,8 +26,11 @@ inline T parseFloat(const char* s) {
|
||||
switch (*s) {
|
||||
case '-':
|
||||
negative_result = true;
|
||||
s++;
|
||||
break;
|
||||
case '+':
|
||||
s++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (*s == 't') return 1; // true
|
||||
|
@ -26,6 +26,8 @@ T parseInteger(const char *s) {
|
||||
switch (*s) {
|
||||
case '-':
|
||||
negative_result = true;
|
||||
s++;
|
||||
break;
|
||||
case '+':
|
||||
s++;
|
||||
break;
|
||||
|
92
src/ArduinoJson/Serialization/FloatParts.hpp
Normal file
92
src/ArduinoJson/Serialization/FloatParts.hpp
Normal file
@ -0,0 +1,92 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../Configuration.hpp"
|
||||
#include "../Polyfills/math.hpp"
|
||||
#include "../TypeTraits/FloatTraits.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
|
||||
template <typename TFloat>
|
||||
struct FloatParts {
|
||||
uint32_t integral;
|
||||
uint32_t decimal;
|
||||
int16_t exponent;
|
||||
int8_t decimalPlaces;
|
||||
|
||||
FloatParts(TFloat value) {
|
||||
uint32_t maxDecimalPart = sizeof(TFloat) >= 8 ? 1000000000 : 1000000;
|
||||
decimalPlaces = sizeof(TFloat) >= 8 ? 9 : 6;
|
||||
|
||||
exponent = normalize(value);
|
||||
|
||||
integral = uint32_t(value);
|
||||
// reduce number of decimal places by the number of integral places
|
||||
for (uint32_t tmp = integral; tmp >= 10; tmp /= 10) {
|
||||
maxDecimalPart /= 10;
|
||||
decimalPlaces--;
|
||||
}
|
||||
|
||||
TFloat remainder = (value - TFloat(integral)) * TFloat(maxDecimalPart);
|
||||
|
||||
decimal = uint32_t(remainder);
|
||||
remainder = remainder - TFloat(decimal);
|
||||
|
||||
// rounding:
|
||||
// increment by 1 if remainder >= 0.5
|
||||
decimal += uint32_t(remainder * 2);
|
||||
if (decimal >= maxDecimalPart) {
|
||||
decimal = 0;
|
||||
integral++;
|
||||
if (exponent && integral >= 10) {
|
||||
exponent++;
|
||||
integral = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// remove trailing zeros
|
||||
while (decimal % 10 == 0 && decimalPlaces > 0) {
|
||||
decimal /= 10;
|
||||
decimalPlaces--;
|
||||
}
|
||||
}
|
||||
|
||||
static int16_t normalize(TFloat& value) {
|
||||
typedef TypeTraits::FloatTraits<TFloat> traits;
|
||||
int16_t powersOf10 = 0;
|
||||
|
||||
int8_t index = sizeof(TFloat) == 8 ? 8 : 5;
|
||||
int bit = 1 << index;
|
||||
|
||||
if (value >= ARDUINOJSON_POSITIVE_EXPONENTIATION_THRESHOLD) {
|
||||
for (; index >= 0; index--) {
|
||||
if (value >= traits::positiveBinaryPowerOfTen(index)) {
|
||||
value *= traits::negativeBinaryPowerOfTen(index);
|
||||
powersOf10 = int16_t(powersOf10 + bit);
|
||||
}
|
||||
bit >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (value > 0 && value <= ARDUINOJSON_NEGATIVE_EXPONENTIATION_THRESHOLD) {
|
||||
for (; index >= 0; index--) {
|
||||
if (value < traits::negativeBinaryPowerOfTenPlusOne(index)) {
|
||||
value *= traits::positiveBinaryPowerOfTen(index);
|
||||
powersOf10 = int16_t(powersOf10 - bit);
|
||||
}
|
||||
bit >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return powersOf10;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -90,7 +90,8 @@ inline void ArduinoJson::Internals::JsonSerializer<Writer>::serialize(
|
||||
return;
|
||||
|
||||
case JSON_NEGATIVE_INTEGER:
|
||||
writer.writeRaw('-');
|
||||
writer.writeRaw('-'); // Falls through.
|
||||
|
||||
case JSON_POSITIVE_INTEGER:
|
||||
writer.writeInteger(variant._content.asInteger);
|
||||
return;
|
||||
|
@ -9,12 +9,9 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include "../Data/Encoding.hpp"
|
||||
#include "../Data/JsonFloat.hpp"
|
||||
#include "../Data/JsonInteger.hpp"
|
||||
#include "../Polyfills/attributes.hpp"
|
||||
#include "../Polyfills/math.hpp"
|
||||
#include "../Polyfills/normalize.hpp"
|
||||
#include "../TypeTraits/FloatTraits.hpp"
|
||||
#include "../Serialization/FloatParts.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace Internals {
|
||||
@ -28,10 +25,6 @@ namespace Internals {
|
||||
// indentation.
|
||||
template <typename Print>
|
||||
class JsonWriter {
|
||||
static const uint8_t maxDecimalPlaces = sizeof(JsonFloat) >= 8 ? 9 : 6;
|
||||
static const uint32_t maxDecimalPart =
|
||||
sizeof(JsonFloat) >= 8 ? 1000000000 : 1000000;
|
||||
|
||||
public:
|
||||
explicit JsonWriter(Print &sink) : _sink(sink), _length(0) {}
|
||||
|
||||
@ -87,7 +80,8 @@ class JsonWriter {
|
||||
}
|
||||
}
|
||||
|
||||
void writeFloat(JsonFloat value) {
|
||||
template <typename TFloat>
|
||||
void writeFloat(TFloat value) {
|
||||
if (Polyfills::isNaN(value)) return writeRaw("NaN");
|
||||
|
||||
if (value < 0.0) {
|
||||
@ -97,28 +91,27 @@ class JsonWriter {
|
||||
|
||||
if (Polyfills::isInfinity(value)) return writeRaw("Infinity");
|
||||
|
||||
uint32_t integralPart, decimalPart;
|
||||
int16_t powersOf10;
|
||||
splitFloat(value, integralPart, decimalPart, powersOf10);
|
||||
FloatParts<TFloat> parts(value);
|
||||
|
||||
writeInteger(integralPart);
|
||||
if (decimalPart) writeDecimals(decimalPart, maxDecimalPlaces);
|
||||
writeInteger(parts.integral);
|
||||
if (parts.decimalPlaces) writeDecimals(parts.decimal, parts.decimalPlaces);
|
||||
|
||||
if (powersOf10 < 0) {
|
||||
if (parts.exponent < 0) {
|
||||
writeRaw("e-");
|
||||
writeInteger(-powersOf10);
|
||||
writeInteger(-parts.exponent);
|
||||
}
|
||||
|
||||
if (powersOf10 > 0) {
|
||||
if (parts.exponent > 0) {
|
||||
writeRaw('e');
|
||||
writeInteger(powersOf10);
|
||||
writeInteger(parts.exponent);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename UInt>
|
||||
void writeInteger(UInt value) {
|
||||
char buffer[22];
|
||||
char *ptr = buffer + sizeof(buffer) - 1;
|
||||
char *end = buffer + sizeof(buffer) - 1;
|
||||
char *ptr = end;
|
||||
|
||||
*ptr = 0;
|
||||
do {
|
||||
@ -130,15 +123,9 @@ class JsonWriter {
|
||||
}
|
||||
|
||||
void writeDecimals(uint32_t value, int8_t width) {
|
||||
// remove trailing zeros
|
||||
while (value % 10 == 0 && width > 0) {
|
||||
value /= 10;
|
||||
width--;
|
||||
}
|
||||
|
||||
// buffer should be big enough for all digits, the dot and the null
|
||||
// terminator
|
||||
char buffer[maxDecimalPlaces + 2];
|
||||
char buffer[16];
|
||||
char *ptr = buffer + sizeof(buffer) - 1;
|
||||
|
||||
// write the string in reverse order
|
||||
@ -166,30 +153,6 @@ class JsonWriter {
|
||||
|
||||
private:
|
||||
JsonWriter &operator=(const JsonWriter &); // cannot be assigned
|
||||
|
||||
void splitFloat(JsonFloat value, uint32_t &integralPart,
|
||||
uint32_t &decimalPart, int16_t &powersOf10) {
|
||||
powersOf10 = Polyfills::normalize(value);
|
||||
|
||||
integralPart = uint32_t(value);
|
||||
JsonFloat remainder = value - JsonFloat(integralPart);
|
||||
|
||||
remainder *= maxDecimalPart;
|
||||
decimalPart = uint32_t(remainder);
|
||||
remainder = remainder - JsonFloat(decimalPart);
|
||||
|
||||
// rounding:
|
||||
// increment by 1 if remainder >= 0.5
|
||||
decimalPart += uint32_t(remainder * 2);
|
||||
if (decimalPart >= maxDecimalPart) {
|
||||
decimalPart = 0;
|
||||
integralPart++;
|
||||
if (powersOf10 && integralPart >= 10) {
|
||||
powersOf10++;
|
||||
integralPart = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -9,16 +9,6 @@
|
||||
|
||||
#include "JsonBufferBase.hpp"
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#elif defined(__GNUC__)
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
#pragma GCC diagnostic push
|
||||
#endif
|
||||
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#endif
|
||||
|
||||
namespace ArduinoJson {
|
||||
|
||||
class StaticJsonBufferBase : public JsonBufferBase<StaticJsonBufferBase> {
|
||||
@ -81,6 +71,9 @@ class StaticJsonBufferBase : public JsonBufferBase<StaticJsonBufferBase> {
|
||||
return String(this);
|
||||
}
|
||||
|
||||
protected:
|
||||
~StaticJsonBufferBase() {}
|
||||
|
||||
private:
|
||||
void alignNextAlloc() {
|
||||
_size = round_size_up(_size);
|
||||
@ -101,6 +94,16 @@ class StaticJsonBufferBase : public JsonBufferBase<StaticJsonBufferBase> {
|
||||
size_t _size;
|
||||
};
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#elif defined(__GNUC__)
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
#pragma GCC diagnostic push
|
||||
#endif
|
||||
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
|
||||
#endif
|
||||
|
||||
// Implements a JsonBuffer with fixed memory allocation.
|
||||
// The template paramenter CAPACITY specifies the capacity of the buffer in
|
||||
// bytes.
|
||||
|
@ -34,15 +34,15 @@ struct StringTraits<const __FlashStringHelper*, void> {
|
||||
};
|
||||
|
||||
static bool equals(const __FlashStringHelper* str, const char* expected) {
|
||||
return strcmp_P(expected, (PGM_P)str) == 0;
|
||||
return strcmp_P(expected, (const char*)str) == 0;
|
||||
}
|
||||
|
||||
template <typename Buffer>
|
||||
static char* duplicate(const __FlashStringHelper* str, Buffer* buffer) {
|
||||
if (!str) return NULL;
|
||||
size_t size = strlen_P((PGM_P)str) + 1;
|
||||
size_t size = strlen_P((const char*)str) + 1;
|
||||
void* dup = buffer->alloc(size);
|
||||
if (dup != NULL) memcpy_P(dup, (PGM_P)str, size);
|
||||
if (dup != NULL) memcpy_P(dup, (const char*)str, size);
|
||||
return static_cast<char*>(dup);
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,6 @@ namespace TypeTraits {
|
||||
template <typename T, size_t = sizeof(T)>
|
||||
struct FloatTraits {};
|
||||
|
||||
#if ARDUINOJSON_DOUBLE_IS_64BITS
|
||||
template <typename T>
|
||||
struct FloatTraits<T, 8 /*64bits*/> {
|
||||
typedef int64_t mantissa_type;
|
||||
@ -31,29 +30,65 @@ struct FloatTraits<T, 8 /*64bits*/> {
|
||||
|
||||
template <typename TExponent>
|
||||
static T make_float(T m, TExponent e) {
|
||||
if (e >= 0)
|
||||
return m * (e & 1 ? 1e1 : 1) * (e & 2 ? 1e2 : 1) * (e & 4 ? 1e4 : 1) *
|
||||
(e & 8 ? 1e8 : 1) * (e & 16 ? 1e16 : 1) * (e & 32 ? 1e32 : 1) *
|
||||
(e & 64 ? 1e64 : 1) * (e & 128 ? 1e128 : 1) *
|
||||
(e & 256 ? 1e256 : 1);
|
||||
e = TExponent(-e);
|
||||
return m * (e & 1 ? 1e-1 : 1) * (e & 2 ? 1e-2 : 1) * (e & 4 ? 1e-4 : 1) *
|
||||
(e & 8 ? 1e-8 : 1) * (e & 16 ? 1e-16 : 1) * (e & 32 ? 1e-32 : 1) *
|
||||
(e & 64 ? 1e-64 : 1) * (e & 128 ? 1e-128 : 1) *
|
||||
(e & 256 ? 1e-256 : 1);
|
||||
if (e > 0) {
|
||||
for (uint8_t index = 0; e != 0; index++) {
|
||||
if (e & 1) m *= positiveBinaryPowerOfTen(index);
|
||||
e >>= 1;
|
||||
}
|
||||
} else {
|
||||
e = TExponent(-e);
|
||||
for (uint8_t index = 0; e != 0; index++) {
|
||||
if (e & 1) m *= negativeBinaryPowerOfTen(index);
|
||||
e >>= 1;
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
static T positiveBinaryPowerOfTen(int index) {
|
||||
static T factors[] = {
|
||||
1e1, 1e2, 1e4, 1e8, 1e16, 1e32,
|
||||
// workaround to support platforms with single precision literals
|
||||
forge(0x4D384F03, 0xE93FF9F5), forge(0x5A827748, 0xF9301D32),
|
||||
forge(0x75154FDD, 0x7F73BF3C)};
|
||||
return factors[index];
|
||||
}
|
||||
|
||||
static T negativeBinaryPowerOfTen(int index) {
|
||||
static T factors[] = {
|
||||
1e-1, 1e-2, 1e-4, 1e-8, 1e-16, 1e-32,
|
||||
// workaround to support platforms with single precision literals
|
||||
forge(0x32A50FFD, 0x44F4A73D), forge(0x255BBA08, 0xCF8C979D),
|
||||
forge(0x0AC80628, 0x64AC6F43)};
|
||||
return factors[index];
|
||||
}
|
||||
|
||||
static T negativeBinaryPowerOfTenPlusOne(int index) {
|
||||
static T factors[] = {
|
||||
1e0, 1e-1, 1e-3, 1e-7, 1e-15, 1e-31,
|
||||
// workaround to support platforms with single precision literals
|
||||
forge(0x32DA53FC, 0x9631D10D), forge(0x25915445, 0x81B7DEC2),
|
||||
forge(0x0AFE07B2, 0x7DD78B14)};
|
||||
return factors[index];
|
||||
}
|
||||
|
||||
static T nan() {
|
||||
uint64_t x = uint64_t(0x7ff8) << 48;
|
||||
return *reinterpret_cast<T*>(&x);
|
||||
return forge(0x7ff80000, 0x00000000);
|
||||
}
|
||||
|
||||
static T inf() {
|
||||
uint64_t x = uint64_t(0x7ff0) << 48;
|
||||
return *reinterpret_cast<T*>(&x);
|
||||
return forge(0x7ff00000, 0x00000000);
|
||||
}
|
||||
|
||||
static T forge(uint32_t msb, uint32_t lsb) {
|
||||
union {
|
||||
uint64_t integerBits;
|
||||
T floatBits;
|
||||
};
|
||||
integerBits = (uint64_t(msb) << 32) | lsb;
|
||||
return floatBits;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
struct FloatTraits<T, 4 /*32bits*/> {
|
||||
@ -67,22 +102,51 @@ struct FloatTraits<T, 4 /*32bits*/> {
|
||||
|
||||
template <typename TExponent>
|
||||
static T make_float(T m, TExponent e) {
|
||||
if (e > 0)
|
||||
return m * (e & 1 ? 1e1f : 1) * (e & 2 ? 1e2f : 1) * (e & 4 ? 1e4f : 1) *
|
||||
(e & 8 ? 1e8f : 1) * (e & 16 ? 1e16f : 1) * (e & 32 ? 1e32f : 1);
|
||||
e = -e;
|
||||
return m * (e & 1 ? 1e-1f : 1) * (e & 2 ? 1e-2f : 1) * (e & 4 ? 1e-4f : 1) *
|
||||
(e & 8 ? 1e-8f : 1) * (e & 16 ? 1e-16f : 1) * (e & 32 ? 1e-32f : 1);
|
||||
if (e > 0) {
|
||||
for (uint8_t index = 0; e != 0; index++) {
|
||||
if (e & 1) m *= positiveBinaryPowerOfTen(index);
|
||||
e >>= 1;
|
||||
}
|
||||
} else {
|
||||
e = -e;
|
||||
for (uint8_t index = 0; e != 0; index++) {
|
||||
if (e & 1) m *= negativeBinaryPowerOfTen(index);
|
||||
e >>= 1;
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
static T positiveBinaryPowerOfTen(int index) {
|
||||
static T factors[] = {1e1f, 1e2f, 1e4f, 1e8f, 1e16f, 1e32f};
|
||||
return factors[index];
|
||||
}
|
||||
|
||||
static T negativeBinaryPowerOfTen(int index) {
|
||||
static T factors[] = {1e-1f, 1e-2f, 1e-4f, 1e-8f, 1e-16f, 1e-32f};
|
||||
return factors[index];
|
||||
}
|
||||
|
||||
static T negativeBinaryPowerOfTenPlusOne(int index) {
|
||||
static T factors[] = {1e0f, 1e-1f, 1e-3f, 1e-7f, 1e-15f, 1e-31f};
|
||||
return factors[index];
|
||||
}
|
||||
|
||||
static T forge(uint32_t bits) {
|
||||
union {
|
||||
uint32_t integerBits;
|
||||
T floatBits;
|
||||
};
|
||||
integerBits = bits;
|
||||
return floatBits;
|
||||
}
|
||||
|
||||
static T nan() {
|
||||
uint32_t x = 0x7fc00000;
|
||||
return *reinterpret_cast<T*>(&x);
|
||||
return forge(0x7fc00000);
|
||||
}
|
||||
|
||||
static T inf() {
|
||||
uint32_t x = 0x7f800000;
|
||||
return *reinterpret_cast<T*>(&x);
|
||||
return forge(0x7f800000);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
20
src/ArduinoJson/TypeTraits/IsVariant.hpp
Normal file
20
src/ArduinoJson/TypeTraits/IsVariant.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "IsBaseOf.hpp"
|
||||
|
||||
namespace ArduinoJson {
|
||||
namespace TypeTraits {
|
||||
|
||||
class JsonVariantTag {};
|
||||
|
||||
template <typename T>
|
||||
struct IsVariant : IsBaseOf<JsonVariantTag, T> {};
|
||||
}
|
||||
}
|
@ -19,13 +19,14 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
|
||||
-Wformat=2
|
||||
-Winit-self
|
||||
-Wmissing-include-dirs
|
||||
-Wparentheses
|
||||
-Wnon-virtual-dtor
|
||||
-Wold-style-cast
|
||||
-Woverloaded-virtual
|
||||
-Wparentheses
|
||||
-Wredundant-decls
|
||||
-Wshadow
|
||||
-Wsign-promo
|
||||
-Wstrict-aliasing
|
||||
-Wstrict-overflow=5
|
||||
-Wundef
|
||||
)
|
||||
|
@ -46,7 +46,7 @@ TEST_CASE("DynamicJsonBuffer::alloc()") {
|
||||
REQUIRE(allocatorLog.str() == "A1A2FF");
|
||||
}
|
||||
|
||||
SECTION("Keeps increasing allocation size after clear") {
|
||||
SECTION("Resets allocation size after clear()") {
|
||||
allocatorLog.str("");
|
||||
{
|
||||
DynamicJsonBufferBase<SpyingAllocator> buffer(1);
|
||||
@ -55,7 +55,7 @@ TEST_CASE("DynamicJsonBuffer::alloc()") {
|
||||
buffer.clear();
|
||||
buffer.alloc(1);
|
||||
}
|
||||
REQUIRE(allocatorLog.str() == "A1A2FFA4F");
|
||||
REQUIRE(allocatorLog.str() == "A1A2FFA1F");
|
||||
}
|
||||
|
||||
SECTION("Makes a big allocation when needed") {
|
||||
|
@ -10,5 +10,12 @@ add_executable(IntegrationTests
|
||||
round_trip.cpp
|
||||
)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
target_compile_options(IntegrationTests
|
||||
PUBLIC
|
||||
-fsingle-precision-constant # issue 544
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(IntegrationTests catch)
|
||||
add_test(IntegrationTests IntegrationTests)
|
||||
|
@ -14,7 +14,8 @@
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
void check(double input, const std::string& expected) {
|
||||
template <typename TFloat>
|
||||
void check(TFloat input, const std::string& expected) {
|
||||
std::string output;
|
||||
DynamicStringBuilder<std::string> sb(output);
|
||||
JsonWriter<DynamicStringBuilder<std::string> > writer(sb);
|
||||
@ -23,83 +24,97 @@ void check(double input, const std::string& expected) {
|
||||
CHECK(expected == output);
|
||||
}
|
||||
|
||||
TEST_CASE("JsonWriter::writeFloat()") {
|
||||
TEST_CASE("JsonWriter::writeFloat(double)") {
|
||||
SECTION("Pi") {
|
||||
check(3.14159265359, "3.141592654");
|
||||
check<double>(3.14159265359, "3.141592654");
|
||||
}
|
||||
|
||||
SECTION("Signaling NaN") {
|
||||
double nan = std::numeric_limits<double>::signaling_NaN();
|
||||
check(nan, "NaN");
|
||||
check<double>(nan, "NaN");
|
||||
}
|
||||
|
||||
SECTION("Quiet NaN") {
|
||||
double nan = std::numeric_limits<double>::quiet_NaN();
|
||||
check(nan, "NaN");
|
||||
check<double>(nan, "NaN");
|
||||
}
|
||||
|
||||
SECTION("Infinity") {
|
||||
double inf = std::numeric_limits<double>::infinity();
|
||||
check(inf, "Infinity");
|
||||
check(-inf, "-Infinity");
|
||||
check<double>(inf, "Infinity");
|
||||
check<double>(-inf, "-Infinity");
|
||||
}
|
||||
|
||||
SECTION("Zero") {
|
||||
check(0.0, "0");
|
||||
check(-0.0, "0");
|
||||
check<double>(0.0, "0");
|
||||
check<double>(-0.0, "0");
|
||||
}
|
||||
|
||||
SECTION("Espilon") {
|
||||
check(2.2250738585072014E-308, "2.225073859e-308");
|
||||
check(-2.2250738585072014E-308, "-2.225073859e-308");
|
||||
check<double>(2.2250738585072014E-308, "2.225073859e-308");
|
||||
check<double>(-2.2250738585072014E-308, "-2.225073859e-308");
|
||||
}
|
||||
|
||||
SECTION("Max double") {
|
||||
check(1.7976931348623157E+308, "1.797693135e308");
|
||||
check(-1.7976931348623157E+308, "-1.797693135e308");
|
||||
check<double>(1.7976931348623157E+308, "1.797693135e308");
|
||||
check<double>(-1.7976931348623157E+308, "-1.797693135e308");
|
||||
}
|
||||
|
||||
SECTION("Big exponent") {
|
||||
// this test increases coverage of normalize()
|
||||
check(1e255, "1e255");
|
||||
check(1e-255, "1e-255");
|
||||
check<double>(1e255, "1e255");
|
||||
check<double>(1e-255, "1e-255");
|
||||
}
|
||||
|
||||
SECTION("Exponentation when <= 1e-5") {
|
||||
check(1e-4, "0.0001");
|
||||
check(1e-5, "1e-5");
|
||||
check<double>(1e-4, "0.0001");
|
||||
check<double>(1e-5, "1e-5");
|
||||
|
||||
check(-1e-4, "-0.0001");
|
||||
check(-1e-5, "-1e-5");
|
||||
check<double>(-1e-4, "-0.0001");
|
||||
check<double>(-1e-5, "-1e-5");
|
||||
}
|
||||
|
||||
SECTION("Exponentation when >= 1e7") {
|
||||
check(9999999.999, "9999999.999");
|
||||
check(10000000, "1e7");
|
||||
check<double>(9999999.999, "9999999.999");
|
||||
check<double>(10000000.0, "1e7");
|
||||
|
||||
check(-9999999.999, "-9999999.999");
|
||||
check(-10000000, "-1e7");
|
||||
check<double>(-9999999.999, "-9999999.999");
|
||||
check<double>(-10000000.0, "-1e7");
|
||||
}
|
||||
|
||||
SECTION("Rounding when too many decimals") {
|
||||
check(0.000099999999999, "0.0001");
|
||||
check(0.0000099999999999, "1e-5");
|
||||
check(0.9999999996, "1");
|
||||
check<double>(0.000099999999999, "0.0001");
|
||||
check<double>(0.0000099999999999, "1e-5");
|
||||
check<double>(0.9999999996, "1");
|
||||
}
|
||||
|
||||
SECTION("9 decimal places") {
|
||||
check(0.100000001, "0.100000001");
|
||||
check(0.999999999, "0.999999999");
|
||||
check<double>(0.100000001, "0.100000001");
|
||||
check<double>(0.999999999, "0.999999999");
|
||||
|
||||
check(9.000000001, "9.000000001");
|
||||
check(9.999999999, "9.999999999");
|
||||
check<double>(9.000000001, "9.000000001");
|
||||
check<double>(9.999999999, "9.999999999");
|
||||
}
|
||||
|
||||
SECTION("10 decimal places") {
|
||||
check(0.1000000001, "0.1");
|
||||
check(0.9999999999, "1");
|
||||
check<double>(0.1000000001, "0.1");
|
||||
check<double>(0.9999999999, "1");
|
||||
|
||||
check(9.0000000001, "9");
|
||||
check(9.9999999999, "10");
|
||||
check<double>(9.0000000001, "9");
|
||||
check<double>(9.9999999999, "10");
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("JsonWriter::writeFloat(float)") {
|
||||
SECTION("Pi") {
|
||||
check<float>(3.14159265359f, "3.141593");
|
||||
}
|
||||
|
||||
SECTION("999.9") { // issue #543
|
||||
check<float>(999.9f, "999.9");
|
||||
}
|
||||
|
||||
SECTION("24.3") { // # issue #588
|
||||
check<float>(24.3f, "24.3");
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
add_executable(MiscTests
|
||||
deprecated.cpp
|
||||
FloatParts.cpp
|
||||
std_stream.cpp
|
||||
std_string.cpp
|
||||
StringBuilder.cpp
|
||||
|
47
test/Misc/FloatParts.cpp
Normal file
47
test/Misc/FloatParts.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright Benoit Blanchon 2014-2017
|
||||
// MIT License
|
||||
//
|
||||
// Arduino JSON library
|
||||
// https://bblanchon.github.io/ArduinoJson/
|
||||
// If you like this project, please add a star!
|
||||
|
||||
#include <ArduinoJson/Serialization/FloatParts.hpp>
|
||||
#include <catch.hpp>
|
||||
|
||||
using namespace ArduinoJson::Internals;
|
||||
|
||||
TEST_CASE("FloatParts<double>") {
|
||||
SECTION("1.7976931348623157E+308") {
|
||||
FloatParts<double> parts(1.7976931348623157E+308);
|
||||
REQUIRE(parts.integral == 1);
|
||||
REQUIRE(parts.decimal == 797693135);
|
||||
REQUIRE(parts.decimalPlaces == 9);
|
||||
REQUIRE(parts.exponent == 308);
|
||||
}
|
||||
|
||||
SECTION("4.94065645841247e-324") {
|
||||
FloatParts<double> parts(4.94065645841247e-324);
|
||||
REQUIRE(parts.integral == 4);
|
||||
REQUIRE(parts.decimal == 940656458);
|
||||
REQUIRE(parts.decimalPlaces == 9);
|
||||
REQUIRE(parts.exponent == -324);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("FloatParts<float>") {
|
||||
SECTION("3.4E+38") {
|
||||
FloatParts<float> parts(3.4E+38f);
|
||||
REQUIRE(parts.integral == 3);
|
||||
REQUIRE(parts.decimal == 4);
|
||||
REQUIRE(parts.decimalPlaces == 1);
|
||||
REQUIRE(parts.exponent == 38);
|
||||
}
|
||||
|
||||
SECTION("1.17549435e−38") {
|
||||
FloatParts<float> parts(1.17549435e-38f);
|
||||
REQUIRE(parts.integral == 1);
|
||||
REQUIRE(parts.decimal == 175494);
|
||||
REQUIRE(parts.decimalPlaces == 6);
|
||||
REQUIRE(parts.exponent == -38);
|
||||
}
|
||||
}
|
484
third-party/catch/catch.hpp
vendored
484
third-party/catch/catch.hpp
vendored
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user