mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-16 20:12:16 +02:00
Changed integer storage from positive/negative to signed/unsigned
This commit is contained in:
@ -76,11 +76,28 @@ TEST_CASE("JsonVariant::as()") {
|
||||
REQUIRE(variant.as<std::string>() == "-42");
|
||||
}
|
||||
|
||||
SECTION("set(42UL)") {
|
||||
variant.set(42UL);
|
||||
|
||||
REQUIRE(variant.as<bool>() == true);
|
||||
REQUIRE(variant.as<double>() == 42.0);
|
||||
REQUIRE(variant.as<std::string>() == "42");
|
||||
}
|
||||
|
||||
SECTION("set(0L)") {
|
||||
variant.set(0L);
|
||||
|
||||
REQUIRE(variant.as<bool>() == false);
|
||||
REQUIRE(variant.as<double>() == 0.0);
|
||||
REQUIRE(variant.as<std::string>() == "0");
|
||||
}
|
||||
|
||||
SECTION("set(0UL)") {
|
||||
variant.set(0UL);
|
||||
|
||||
REQUIRE(variant.as<bool>() == false);
|
||||
REQUIRE(variant.as<double>() == 0.0);
|
||||
REQUIRE(variant.as<std::string>() == "0");
|
||||
}
|
||||
|
||||
SECTION("set(null)") {
|
||||
|
@ -46,8 +46,14 @@ TEST_CASE("serialize MsgPack value") {
|
||||
}
|
||||
|
||||
SECTION("positive fixint") {
|
||||
checkVariant(0, "\x00");
|
||||
checkVariant(127, "\x7F");
|
||||
SECTION("signed") {
|
||||
checkVariant(0, "\x00");
|
||||
checkVariant(127, "\x7F");
|
||||
}
|
||||
SECTION("unsigned") {
|
||||
checkVariant(0U, "\x00");
|
||||
checkVariant(127U, "\x7F");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("uint 8") {
|
||||
|
@ -47,6 +47,7 @@ TEST_CASE("parseNumber<int32_t>()") {
|
||||
|
||||
TEST_CASE("parseNumber<uint8_t>()") {
|
||||
checkInteger<uint8_t>("0", 0);
|
||||
checkInteger<uint8_t>("-0", 0);
|
||||
checkInteger<uint8_t>("255", 255);
|
||||
checkInteger<uint8_t>("+255", 255);
|
||||
checkInteger<uint8_t>("3.14", 3);
|
||||
|
@ -23,7 +23,27 @@ TEST_CASE("Test unsigned integer overflow") {
|
||||
parseNumber("4294967296", second);
|
||||
}
|
||||
|
||||
REQUIRE(first.type() == uint8_t(VALUE_IS_POSITIVE_INTEGER));
|
||||
REQUIRE(first.type() == uint8_t(VALUE_IS_UNSIGNED_INTEGER));
|
||||
REQUIRE(second.type() == uint8_t(VALUE_IS_FLOAT));
|
||||
}
|
||||
|
||||
TEST_CASE("Test signed integer overflow") {
|
||||
VariantData first, second;
|
||||
first.init();
|
||||
second.init();
|
||||
|
||||
// Avoids MSVC warning C4127 (conditional expression is constant)
|
||||
size_t integerSize = sizeof(Integer);
|
||||
|
||||
if (integerSize == 8) {
|
||||
parseNumber("-9223372036854775808", first);
|
||||
parseNumber("-9223372036854775809", second);
|
||||
} else {
|
||||
parseNumber("-2147483648", first);
|
||||
parseNumber("-2147483649", second);
|
||||
}
|
||||
|
||||
REQUIRE(first.type() == uint8_t(VALUE_IS_SIGNED_INTEGER));
|
||||
REQUIRE(second.type() == uint8_t(VALUE_IS_FLOAT));
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
add_executable(TextFormatterTests
|
||||
writeFloat.cpp
|
||||
writeInteger.cpp
|
||||
writeString.cpp
|
||||
)
|
||||
|
||||
|
55
extras/tests/TextFormatter/writeInteger.cpp
Normal file
55
extras/tests/TextFormatter/writeInteger.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
// ArduinoJson - https://arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2021
|
||||
// MIT License
|
||||
|
||||
#include <catch.hpp>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include <ArduinoJson/Json/TextFormatter.hpp>
|
||||
#include <ArduinoJson/Serialization/Writer.hpp>
|
||||
|
||||
using namespace ARDUINOJSON_NAMESPACE;
|
||||
|
||||
template <typename T>
|
||||
void checkWriteInteger(T value, std::string expected) {
|
||||
char output[1024];
|
||||
StaticStringWriter sb(output, sizeof(output));
|
||||
TextFormatter<StaticStringWriter> writer(sb);
|
||||
writer.writeInteger<T>(value);
|
||||
REQUIRE(expected == output);
|
||||
REQUIRE(writer.bytesWritten() == expected.size());
|
||||
}
|
||||
|
||||
TEST_CASE("int8_t") {
|
||||
checkWriteInteger<int8_t>(0, "0");
|
||||
checkWriteInteger<int8_t>(-128, "-128");
|
||||
checkWriteInteger<int8_t>(127, "127");
|
||||
}
|
||||
|
||||
TEST_CASE("uint8_t") {
|
||||
checkWriteInteger<uint8_t>(0, "0");
|
||||
checkWriteInteger<uint8_t>(255, "255");
|
||||
}
|
||||
|
||||
TEST_CASE("int16_t") {
|
||||
checkWriteInteger<int16_t>(0, "0");
|
||||
checkWriteInteger<int16_t>(-32768, "-32768");
|
||||
checkWriteInteger<int16_t>(32767, "32767");
|
||||
}
|
||||
|
||||
TEST_CASE("uint16_t") {
|
||||
checkWriteInteger<uint16_t>(0, "0");
|
||||
checkWriteInteger<uint16_t>(65535, "65535");
|
||||
}
|
||||
|
||||
TEST_CASE("int32_t") {
|
||||
checkWriteInteger<int32_t>(0, "0");
|
||||
checkWriteInteger<int32_t>(-2147483647 - 1, "-2147483648");
|
||||
checkWriteInteger<int32_t>(2147483647, "2147483647");
|
||||
}
|
||||
|
||||
TEST_CASE("uint32_t") {
|
||||
checkWriteInteger<uint32_t>(0, "0");
|
||||
checkWriteInteger<uint32_t>(4294967295U, "4294967295");
|
||||
}
|
@ -71,13 +71,13 @@ class JsonSerializer : public Visitor<size_t> {
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitNegativeInteger(UInt value) {
|
||||
_formatter.writeNegativeInteger(value);
|
||||
size_t visitSignedInteger(Integer value) {
|
||||
_formatter.writeInteger(value);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitPositiveInteger(UInt value) {
|
||||
_formatter.writePositiveInteger(value);
|
||||
size_t visitUnsignedInteger(UInt value) {
|
||||
_formatter.writeInteger(value);
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <ArduinoJson/Numbers/Integer.hpp>
|
||||
#include <ArduinoJson/Polyfills/assert.hpp>
|
||||
#include <ArduinoJson/Polyfills/attributes.hpp>
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
#include <ArduinoJson/Serialization/CountingDecorator.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
@ -75,28 +76,31 @@ class TextFormatter {
|
||||
|
||||
FloatParts<T> parts(value);
|
||||
|
||||
writePositiveInteger(parts.integral);
|
||||
writeInteger(parts.integral);
|
||||
if (parts.decimalPlaces)
|
||||
writeDecimals(parts.decimal, parts.decimalPlaces);
|
||||
|
||||
if (parts.exponent < 0) {
|
||||
writeRaw("e-");
|
||||
writePositiveInteger(-parts.exponent);
|
||||
}
|
||||
|
||||
if (parts.exponent > 0) {
|
||||
if (parts.exponent) {
|
||||
writeRaw('e');
|
||||
writePositiveInteger(parts.exponent);
|
||||
writeInteger(parts.exponent);
|
||||
}
|
||||
}
|
||||
|
||||
void writeNegativeInteger(UInt value) {
|
||||
writeRaw('-');
|
||||
writePositiveInteger(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void writePositiveInteger(T value) {
|
||||
typename enable_if<is_signed<T>::value>::type writeInteger(T value) {
|
||||
typedef typename make_unsigned<T>::type unsigned_type;
|
||||
unsigned_type unsigned_value;
|
||||
if (value < 0) {
|
||||
writeRaw('-');
|
||||
unsigned_value = static_cast<unsigned_type>(-value);
|
||||
} else {
|
||||
unsigned_value = static_cast<unsigned_type>(value);
|
||||
}
|
||||
writeInteger(unsigned_value);
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -101,30 +101,37 @@ class MsgPackSerializer : public Visitor<size_t> {
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitNegativeInteger(UInt value) {
|
||||
UInt negated = UInt(~value + 1);
|
||||
if (value <= 0x20) {
|
||||
writeInteger(int8_t(negated));
|
||||
} else if (value <= 0x80) {
|
||||
size_t visitSignedInteger(Integer value) {
|
||||
if (value > 0) {
|
||||
visitUnsignedInteger(static_cast<UInt>(value));
|
||||
} else if (value >= -0x20) {
|
||||
writeInteger(int8_t(value));
|
||||
} else if (value >= -0x80) {
|
||||
writeByte(0xD0);
|
||||
writeInteger(int8_t(negated));
|
||||
} else if (value <= 0x8000) {
|
||||
writeInteger(int8_t(value));
|
||||
} else if (value >= -0x8000) {
|
||||
writeByte(0xD1);
|
||||
writeInteger(int16_t(negated));
|
||||
} else if (value <= 0x80000000) {
|
||||
writeInteger(int16_t(value));
|
||||
}
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
else if (value >= -0x80000000LL)
|
||||
#else
|
||||
else
|
||||
#endif
|
||||
{
|
||||
writeByte(0xD2);
|
||||
writeInteger(int32_t(negated));
|
||||
writeInteger(int32_t(value));
|
||||
}
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
else {
|
||||
writeByte(0xD3);
|
||||
writeInteger(int64_t(negated));
|
||||
writeInteger(int64_t(value));
|
||||
}
|
||||
#endif
|
||||
return bytesWritten();
|
||||
}
|
||||
|
||||
size_t visitPositiveInteger(UInt value) {
|
||||
size_t visitUnsignedInteger(UInt value) {
|
||||
if (value <= 0x7F) {
|
||||
writeInteger(uint8_t(value));
|
||||
} else if (value <= 0xFF) {
|
||||
|
@ -15,84 +15,86 @@
|
||||
#endif
|
||||
|
||||
#include <ArduinoJson/Numbers/Float.hpp>
|
||||
#include <ArduinoJson/Numbers/FloatTraits.hpp>
|
||||
#include <ArduinoJson/Numbers/Integer.hpp>
|
||||
#include <ArduinoJson/Polyfills/limits.hpp>
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
// uint32 -> int32
|
||||
// uint64 -> int32
|
||||
template <typename TOut, typename TIn>
|
||||
typename enable_if<is_integral<TOut>::value && sizeof(TOut) <= sizeof(TIn),
|
||||
typename enable_if<is_integral<TIn>::value && is_unsigned<TIn>::value &&
|
||||
is_integral<TOut>::value && sizeof(TOut) <= sizeof(TIn),
|
||||
bool>::type
|
||||
canStorePositiveInteger(TIn value) {
|
||||
canConvertNumber(TIn value) {
|
||||
return value <= TIn(numeric_limits<TOut>::highest());
|
||||
}
|
||||
|
||||
// uint32 -> int64
|
||||
template <typename TOut, typename TIn>
|
||||
typename enable_if<is_integral<TOut>::value && sizeof(TIn) < sizeof(TOut),
|
||||
typename enable_if<is_integral<TIn>::value && is_unsigned<TIn>::value &&
|
||||
is_integral<TOut>::value && sizeof(TIn) < sizeof(TOut),
|
||||
bool>::type
|
||||
canStorePositiveInteger(TIn) {
|
||||
canConvertNumber(TIn) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// uint32 -> float
|
||||
// int32 -> float
|
||||
template <typename TOut, typename TIn>
|
||||
typename enable_if<is_floating_point<TOut>::value, bool>::type
|
||||
canStorePositiveInteger(TIn) {
|
||||
typename enable_if<is_integral<TIn>::value && is_floating_point<TOut>::value,
|
||||
bool>::type
|
||||
canConvertNumber(TIn) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// int64 -> int32
|
||||
template <typename TOut, typename TIn>
|
||||
typename enable_if<is_floating_point<TOut>::value, bool>::type
|
||||
canStoreNegativeInteger(TIn) {
|
||||
typename enable_if<is_integral<TIn>::value && is_signed<TIn>::value &&
|
||||
is_integral<TOut>::value && is_signed<TOut>::value &&
|
||||
sizeof(TOut) < sizeof(TIn),
|
||||
bool>::type
|
||||
canConvertNumber(TIn value) {
|
||||
return value >= TIn(numeric_limits<TOut>::lowest()) &&
|
||||
value <= TIn(numeric_limits<TOut>::highest());
|
||||
}
|
||||
|
||||
// int32 -> int32
|
||||
// int32 -> int64
|
||||
template <typename TOut, typename TIn>
|
||||
typename enable_if<is_integral<TIn>::value && is_signed<TIn>::value &&
|
||||
is_integral<TOut>::value && is_signed<TOut>::value &&
|
||||
sizeof(TIn) <= sizeof(TOut),
|
||||
bool>::type
|
||||
canConvertNumber(TIn) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// int32 -> uint32
|
||||
template <typename TOut, typename TIn>
|
||||
typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value &&
|
||||
sizeof(TOut) <= sizeof(TIn),
|
||||
typename enable_if<is_integral<TIn>::value && is_signed<TIn>::value &&
|
||||
is_integral<TOut>::value && is_unsigned<TOut>::value,
|
||||
bool>::type
|
||||
canStoreNegativeInteger(TIn value) {
|
||||
return value <= TIn(numeric_limits<TOut>::highest()) + 1;
|
||||
canConvertNumber(TIn value) {
|
||||
if (value < 0)
|
||||
return false;
|
||||
return value <= TIn(numeric_limits<TOut>::highest());
|
||||
}
|
||||
|
||||
// float -> int32
|
||||
// float -> int64
|
||||
template <typename TOut, typename TIn>
|
||||
typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value &&
|
||||
sizeof(TIn) < sizeof(TOut),
|
||||
typename enable_if<is_floating_point<TIn>::value &&
|
||||
!is_floating_point<TOut>::value,
|
||||
bool>::type
|
||||
canStoreNegativeInteger(TIn) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TOut, typename TIn>
|
||||
typename enable_if<is_integral<TOut>::value && is_unsigned<TOut>::value,
|
||||
bool>::type
|
||||
canStoreNegativeInteger(TIn) {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename TOut, typename TIn>
|
||||
TOut convertPositiveInteger(TIn value) {
|
||||
return canStorePositiveInteger<TOut>(value) ? TOut(value) : 0;
|
||||
}
|
||||
|
||||
template <typename TOut, typename TIn>
|
||||
TOut convertNegativeInteger(TIn value) {
|
||||
return canStoreNegativeInteger<TOut>(value) ? TOut(~value + 1) : 0;
|
||||
}
|
||||
|
||||
template <typename TOut, typename TIn>
|
||||
typename enable_if<is_floating_point<TOut>::value, TOut>::type convertFloat(
|
||||
TIn value) {
|
||||
return TOut(value);
|
||||
}
|
||||
|
||||
template <typename TOut, typename TIn>
|
||||
typename enable_if<!is_floating_point<TOut>::value, TOut>::type convertFloat(
|
||||
TIn value) {
|
||||
canConvertNumber(TIn value) {
|
||||
return value >= numeric_limits<TOut>::lowest() &&
|
||||
value <= numeric_limits<TOut>::highest()
|
||||
? TOut(value)
|
||||
: 0;
|
||||
value <= numeric_limits<TOut>::highest();
|
||||
}
|
||||
|
||||
template <typename TOut, typename TIn>
|
||||
TOut convertNumber(TIn value) {
|
||||
return canConvertNumber<TOut>(value) ? TOut(value) : 0;
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
|
@ -69,11 +69,17 @@ inline bool parseNumber(const char* s, VariantData& result) {
|
||||
}
|
||||
|
||||
if (*s == '\0') {
|
||||
if (is_negative)
|
||||
result.setNegativeInteger(UInt(mantissa));
|
||||
else
|
||||
result.setPositiveInteger(UInt(mantissa));
|
||||
return true;
|
||||
if (is_negative) {
|
||||
const mantissa_t sintMantissaMax = mantissa_t(1)
|
||||
<< (sizeof(Integer) * 8 - 1);
|
||||
if (mantissa <= sintMantissaMax) {
|
||||
result.setInteger(Integer(~mantissa + 1));
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
result.setInteger(UInt(mantissa));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// avoid mantissa overflow
|
||||
|
@ -57,16 +57,16 @@ struct Comparer<T, typename enable_if<is_integral<T>::value ||
|
||||
return arithmeticCompare(lhs, rhs);
|
||||
}
|
||||
|
||||
CompareResult visitNegativeInteger(UInt lhs) {
|
||||
return arithmeticCompareNegateLeft(lhs, rhs);
|
||||
CompareResult visitSignedInteger(Integer lhs) {
|
||||
return arithmeticCompare(lhs, rhs);
|
||||
}
|
||||
|
||||
CompareResult visitPositiveInteger(UInt lhs) {
|
||||
CompareResult visitUnsignedInteger(UInt lhs) {
|
||||
return arithmeticCompare(lhs, rhs);
|
||||
}
|
||||
|
||||
CompareResult visitBoolean(bool lhs) {
|
||||
return visitPositiveInteger(static_cast<UInt>(lhs));
|
||||
return visitUnsignedInteger(static_cast<UInt>(lhs));
|
||||
}
|
||||
};
|
||||
|
||||
@ -96,28 +96,6 @@ struct ArrayComparer : ComparerBase {
|
||||
}
|
||||
};
|
||||
|
||||
struct NegativeIntegerComparer : ComparerBase {
|
||||
UInt _rhs;
|
||||
|
||||
explicit NegativeIntegerComparer(UInt rhs) : _rhs(rhs) {}
|
||||
|
||||
CompareResult visitFloat(Float lhs) {
|
||||
return arithmeticCompareNegateRight(lhs, _rhs);
|
||||
}
|
||||
|
||||
CompareResult visitNegativeInteger(UInt lhs) {
|
||||
return arithmeticCompare(_rhs, lhs);
|
||||
}
|
||||
|
||||
CompareResult visitPositiveInteger(UInt) {
|
||||
return COMPARE_RESULT_GREATER;
|
||||
}
|
||||
|
||||
CompareResult visitBoolean(bool) {
|
||||
return COMPARE_RESULT_GREATER;
|
||||
}
|
||||
};
|
||||
|
||||
struct ObjectComparer : ComparerBase {
|
||||
const CollectionData *_rhs;
|
||||
|
||||
@ -182,12 +160,12 @@ struct Comparer<T, typename enable_if<IsVisitable<T>::value>::type>
|
||||
return accept(comparer);
|
||||
}
|
||||
|
||||
CompareResult visitNegativeInteger(UInt lhs) {
|
||||
NegativeIntegerComparer comparer(lhs);
|
||||
CompareResult visitSignedInteger(Integer lhs) {
|
||||
Comparer<Integer> comparer(lhs);
|
||||
return accept(comparer);
|
||||
}
|
||||
|
||||
CompareResult visitPositiveInteger(UInt lhs) {
|
||||
CompareResult visitUnsignedInteger(UInt lhs) {
|
||||
Comparer<UInt> comparer(lhs);
|
||||
return accept(comparer);
|
||||
}
|
||||
|
@ -25,8 +25,8 @@ enum {
|
||||
|
||||
// CAUTION: no VALUE_IS_OWNED below
|
||||
VALUE_IS_BOOLEAN = 0x06,
|
||||
VALUE_IS_POSITIVE_INTEGER = 0x08,
|
||||
VALUE_IS_NEGATIVE_INTEGER = 0x0A,
|
||||
VALUE_IS_UNSIGNED_INTEGER = 0x08,
|
||||
VALUE_IS_SIGNED_INTEGER = 0x0A,
|
||||
VALUE_IS_FLOAT = 0x0C,
|
||||
|
||||
COLLECTION_MASK = 0x60,
|
||||
@ -43,7 +43,9 @@ struct RawData {
|
||||
|
||||
union VariantContent {
|
||||
Float asFloat;
|
||||
UInt asInteger;
|
||||
bool asBoolean;
|
||||
UInt asUnsignedInteger;
|
||||
Integer asSignedInteger;
|
||||
CollectionData asCollection;
|
||||
const char *asString;
|
||||
struct {
|
||||
|
@ -56,14 +56,14 @@ class VariantData {
|
||||
case VALUE_IS_LINKED_RAW:
|
||||
return visitor.visitRawJson(_content.asRaw.data, _content.asRaw.size);
|
||||
|
||||
case VALUE_IS_NEGATIVE_INTEGER:
|
||||
return visitor.visitNegativeInteger(_content.asInteger);
|
||||
case VALUE_IS_SIGNED_INTEGER:
|
||||
return visitor.visitSignedInteger(_content.asSignedInteger);
|
||||
|
||||
case VALUE_IS_POSITIVE_INTEGER:
|
||||
return visitor.visitPositiveInteger(_content.asInteger);
|
||||
case VALUE_IS_UNSIGNED_INTEGER:
|
||||
return visitor.visitUnsignedInteger(_content.asUnsignedInteger);
|
||||
|
||||
case VALUE_IS_BOOLEAN:
|
||||
return visitor.visitBoolean(_content.asInteger != 0);
|
||||
return visitor.visitBoolean(_content.asBoolean != 0);
|
||||
|
||||
default:
|
||||
return visitor.visitNull();
|
||||
@ -129,11 +129,11 @@ class VariantData {
|
||||
template <typename T>
|
||||
bool isInteger() const {
|
||||
switch (type()) {
|
||||
case VALUE_IS_POSITIVE_INTEGER:
|
||||
return canStorePositiveInteger<T>(_content.asInteger);
|
||||
case VALUE_IS_UNSIGNED_INTEGER:
|
||||
return canConvertNumber<T>(_content.asUnsignedInteger);
|
||||
|
||||
case VALUE_IS_NEGATIVE_INTEGER:
|
||||
return canStoreNegativeInteger<T>(_content.asInteger);
|
||||
case VALUE_IS_SIGNED_INTEGER:
|
||||
return canConvertNumber<T>(_content.asSignedInteger);
|
||||
|
||||
default:
|
||||
return false;
|
||||
@ -141,8 +141,8 @@ class VariantData {
|
||||
}
|
||||
|
||||
bool isFloat() const {
|
||||
return type() == VALUE_IS_FLOAT || type() == VALUE_IS_POSITIVE_INTEGER ||
|
||||
type() == VALUE_IS_NEGATIVE_INTEGER;
|
||||
return type() == VALUE_IS_FLOAT || type() == VALUE_IS_UNSIGNED_INTEGER ||
|
||||
type() == VALUE_IS_SIGNED_INTEGER;
|
||||
}
|
||||
|
||||
bool isString() const {
|
||||
@ -174,7 +174,7 @@ class VariantData {
|
||||
|
||||
void setBoolean(bool value) {
|
||||
setType(VALUE_IS_BOOLEAN);
|
||||
_content.asInteger = static_cast<UInt>(value);
|
||||
_content.asBoolean = value;
|
||||
}
|
||||
|
||||
void setFloat(Float value) {
|
||||
@ -208,36 +208,14 @@ class VariantData {
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<is_unsigned<T>::value>::type setInteger(T value) {
|
||||
setUnsignedInteger(value);
|
||||
setType(VALUE_IS_UNSIGNED_INTEGER);
|
||||
_content.asUnsignedInteger = static_cast<UInt>(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename enable_if<is_signed<T>::value>::type setInteger(T value) {
|
||||
setSignedInteger(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void setSignedInteger(T value) {
|
||||
if (value >= 0) {
|
||||
setPositiveInteger(static_cast<UInt>(value));
|
||||
} else {
|
||||
setNegativeInteger(~static_cast<UInt>(value) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void setUnsignedInteger(UInt value) {
|
||||
setType(VALUE_IS_POSITIVE_INTEGER);
|
||||
_content.asInteger = static_cast<UInt>(value);
|
||||
}
|
||||
|
||||
void setPositiveInteger(UInt value) {
|
||||
setType(VALUE_IS_POSITIVE_INTEGER);
|
||||
_content.asInteger = value;
|
||||
}
|
||||
|
||||
void setNegativeInteger(UInt value) {
|
||||
setType(VALUE_IS_NEGATIVE_INTEGER);
|
||||
_content.asInteger = value;
|
||||
setType(VALUE_IS_SIGNED_INTEGER);
|
||||
_content.asSignedInteger = value;
|
||||
}
|
||||
|
||||
void setNull() {
|
||||
|
@ -18,16 +18,17 @@ namespace ARDUINOJSON_NAMESPACE {
|
||||
template <typename T>
|
||||
inline T VariantData::asIntegral() const {
|
||||
switch (type()) {
|
||||
case VALUE_IS_POSITIVE_INTEGER:
|
||||
case VALUE_IS_BOOLEAN:
|
||||
return convertPositiveInteger<T>(_content.asInteger);
|
||||
case VALUE_IS_NEGATIVE_INTEGER:
|
||||
return convertNegativeInteger<T>(_content.asInteger);
|
||||
return _content.asBoolean;
|
||||
case VALUE_IS_UNSIGNED_INTEGER:
|
||||
return convertNumber<T>(_content.asUnsignedInteger);
|
||||
case VALUE_IS_SIGNED_INTEGER:
|
||||
return convertNumber<T>(_content.asSignedInteger);
|
||||
case VALUE_IS_LINKED_STRING:
|
||||
case VALUE_IS_OWNED_STRING:
|
||||
return parseNumber<T>(_content.asString);
|
||||
case VALUE_IS_FLOAT:
|
||||
return convertFloat<T>(_content.asFloat);
|
||||
return convertNumber<T>(_content.asFloat);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -35,10 +36,11 @@ inline T VariantData::asIntegral() const {
|
||||
|
||||
inline bool VariantData::asBoolean() const {
|
||||
switch (type()) {
|
||||
case VALUE_IS_POSITIVE_INTEGER:
|
||||
case VALUE_IS_BOOLEAN:
|
||||
case VALUE_IS_NEGATIVE_INTEGER:
|
||||
return _content.asInteger != 0;
|
||||
return _content.asBoolean;
|
||||
case VALUE_IS_SIGNED_INTEGER:
|
||||
case VALUE_IS_UNSIGNED_INTEGER:
|
||||
return _content.asUnsignedInteger != 0;
|
||||
case VALUE_IS_FLOAT:
|
||||
return _content.asFloat != 0;
|
||||
case VALUE_IS_NULL:
|
||||
@ -52,11 +54,12 @@ inline bool VariantData::asBoolean() const {
|
||||
template <typename T>
|
||||
inline T VariantData::asFloat() const {
|
||||
switch (type()) {
|
||||
case VALUE_IS_POSITIVE_INTEGER:
|
||||
case VALUE_IS_BOOLEAN:
|
||||
return static_cast<T>(_content.asInteger);
|
||||
case VALUE_IS_NEGATIVE_INTEGER:
|
||||
return -static_cast<T>(_content.asInteger);
|
||||
return static_cast<T>(_content.asBoolean);
|
||||
case VALUE_IS_UNSIGNED_INTEGER:
|
||||
return static_cast<T>(_content.asUnsignedInteger);
|
||||
case VALUE_IS_SIGNED_INTEGER:
|
||||
return static_cast<T>(_content.asSignedInteger);
|
||||
case VALUE_IS_LINKED_STRING:
|
||||
case VALUE_IS_OWNED_STRING:
|
||||
return parseNumber<T>(_content.asString);
|
||||
|
@ -26,7 +26,7 @@ struct Visitor {
|
||||
return TResult();
|
||||
}
|
||||
|
||||
TResult visitNegativeInteger(UInt) {
|
||||
TResult visitSignedInteger(Integer) {
|
||||
return TResult();
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ struct Visitor {
|
||||
return TResult();
|
||||
}
|
||||
|
||||
TResult visitPositiveInteger(UInt) {
|
||||
TResult visitUnsignedInteger(UInt) {
|
||||
return TResult();
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user