mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01: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,9 +46,15 @@ TEST_CASE("serialize MsgPack value") { | ||||
|   } | ||||
|  | ||||
|   SECTION("positive fixint") { | ||||
|     SECTION("signed") { | ||||
|       checkVariant(0, "\x00"); | ||||
|       checkVariant(127, "\x7F"); | ||||
|     } | ||||
|     SECTION("unsigned") { | ||||
|       checkVariant(0U, "\x00"); | ||||
|       checkVariant(127U, "\x7F"); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   SECTION("uint 8") { | ||||
|     checkVariant(128, "\xCC\x80"); | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|  | ||||
| template <typename TOut, typename TIn> | ||||
| typename enable_if<is_integral<TOut>::value && is_signed<TOut>::value && | ||||
|                        sizeof(TIn) < sizeof(TOut), | ||||
|                    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) { | ||||
| canConvertNumber(TIn value) { | ||||
|   if (value < 0) | ||||
|     return false; | ||||
|   return value <= TIn(numeric_limits<TOut>::highest()); | ||||
| } | ||||
|  | ||||
| // float -> int32 | ||||
| // float -> int64 | ||||
| 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) { | ||||
| typename enable_if<is_floating_point<TIn>::value && | ||||
|                        !is_floating_point<TOut>::value, | ||||
|                    bool>::type | ||||
| 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,12 +69,18 @@ inline bool parseNumber(const char* s, VariantData& result) { | ||||
|   } | ||||
|  | ||||
|   if (*s == '\0') { | ||||
|     if (is_negative) | ||||
|       result.setNegativeInteger(UInt(mantissa)); | ||||
|     else | ||||
|       result.setPositiveInteger(UInt(mantissa)); | ||||
|     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 | ||||
|   while (mantissa > traits::mantissa_max) { | ||||
|   | ||||
| @@ -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