mirror of
				https://github.com/eledio-devices/thirdparty-ArduinoJson.git
				synced 2025-10-31 16:14:11 +01:00 
			
		
		
		
	Added custom implementation of strtol() (issue #465)
				
					
				
			`char` is now treated as an integral type (issue #337, #370)
This commit is contained in:
		| @@ -5,6 +5,8 @@ HEAD | ||||
| ---- | ||||
|  | ||||
| * Added custom implementation of `strtod()` (issue #453) | ||||
| * Added custom implementation of `strtol()` (issue #465) | ||||
| * `char` is now treated as an integral type (issue #337, #370) | ||||
|  | ||||
| v5.8.3 | ||||
| ------ | ||||
|   | ||||
| @@ -70,13 +70,15 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|   } | ||||
|  | ||||
|   // Create a JsonVariant containing an integer value. | ||||
|   // JsonVariant(char) | ||||
|   // JsonVariant(signed short) | ||||
|   // JsonVariant(signed int) | ||||
|   // JsonVariant(signed long) | ||||
|   // JsonVariant(signed char) | ||||
|   template <typename T> | ||||
|   JsonVariant(T value, | ||||
|               typename TypeTraits::EnableIf< | ||||
|                   TypeTraits::IsSignedIntegral<T>::value>::type * = 0) { | ||||
|   JsonVariant(T value, typename TypeTraits::EnableIf< | ||||
|                            TypeTraits::IsSignedIntegral<T>::value || | ||||
|                            TypeTraits::IsSame<T, char>::value>::type * = 0) { | ||||
|     using namespace Internals; | ||||
|     if (value >= 0) { | ||||
|       _type = JSON_POSITIVE_INTEGER; | ||||
| @@ -129,24 +131,26 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|  | ||||
|   // Get the variant as the specified type. | ||||
|   // | ||||
|   // short as<signed short>() const; | ||||
|   // int as<signed int>() const; | ||||
|   // long as<signed long>() const; | ||||
|   // char as<char>() const; | ||||
|   // signed char as<signed char>() const; | ||||
|   // signed short as<signed short>() const; | ||||
|   // signed int as<signed int>() const; | ||||
|   // signed long as<signed long>() const; | ||||
|   // unsigned char as<unsigned char>() const; | ||||
|   // unsigned short as<unsigned short>() const; | ||||
|   // unsigned int as<unsigned int>() const; | ||||
|   // unsigned long as<unsigned long>() const; | ||||
|   template <typename T> | ||||
|   const typename TypeTraits::EnableIf<TypeTraits::IsSignedIntegral<T>::value, | ||||
|                                       T>::type | ||||
|   const typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value, T>::type | ||||
|   as() const { | ||||
|     return static_cast<T>(variantAsInteger()); | ||||
|     return variantAsInteger<T>(); | ||||
|   } | ||||
|   // | ||||
|   // short as<unsigned short>() const; | ||||
|   // int as<unsigned int>() const; | ||||
|   // long as<unsigned long>() const; | ||||
|   // bool as<bool>() const | ||||
|   template <typename T> | ||||
|   const typename TypeTraits::EnableIf<TypeTraits::IsUnsignedIntegral<T>::value, | ||||
|   const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value, | ||||
|                                       T>::type | ||||
|   as() const { | ||||
|     return static_cast<T>(asUnsignedInteger()); | ||||
|     return variantAsInteger<int>() != 0; | ||||
|   } | ||||
|   // | ||||
|   // double as<double>() const; | ||||
| @@ -155,7 +159,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|   const typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value, | ||||
|                                       T>::type | ||||
|   as() const { | ||||
|     return static_cast<T>(variantAsFloat()); | ||||
|     return variantAsFloat<T>(); | ||||
|   } | ||||
|   // | ||||
|   // const char* as<const char*>() const; | ||||
| @@ -180,14 +184,6 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|     return s; | ||||
|   } | ||||
|   // | ||||
|   // const bool as<bool>() const | ||||
|   template <typename T> | ||||
|   const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value, | ||||
|                                       T>::type | ||||
|   as() const { | ||||
|     return variantAsInteger() != 0; | ||||
|   } | ||||
|   // | ||||
|   // JsonArray& as<JsonArray> const; | ||||
|   // JsonArray& as<JsonArray&> const; | ||||
|   template <typename T> | ||||
| @@ -242,32 +238,35 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|   // Tells weither the variant has the specified type. | ||||
|   // Returns true if the variant has type type T, false otherwise. | ||||
|   // | ||||
|   // short as<short>() const; | ||||
|   // int as<int>() const; | ||||
|   // long as<long>() const; | ||||
|   // bool is<char>() const; | ||||
|   // bool is<signed char>() const; | ||||
|   // bool is<signed short>() const; | ||||
|   // bool is<signed int>() const; | ||||
|   // bool is<signed long>() const; | ||||
|   // bool is<unsigned char>() const; | ||||
|   // bool is<unsigned short>() const; | ||||
|   // bool is<unsigned int>() const; | ||||
|   // bool is<unsigned long>() const; | ||||
|   template <typename T> | ||||
|   const typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value && | ||||
|                                           !TypeTraits::IsSame<T, bool>::value, | ||||
|                                       bool>::type | ||||
|   typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value, bool>::type | ||||
|   is() const { | ||||
|     return isInteger(); | ||||
|     return variantIsInteger(); | ||||
|   } | ||||
|   // | ||||
|   // double is<double>() const; | ||||
|   // float is<float>() const; | ||||
|   // bool is<double>() const; | ||||
|   // bool is<float>() const; | ||||
|   template <typename T> | ||||
|   const typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value, | ||||
|                                       bool>::type | ||||
|   typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value, | ||||
|                                 bool>::type | ||||
|   is() const { | ||||
|     return isFloat(); | ||||
|     return variantIsFloat(); | ||||
|   } | ||||
|   // | ||||
|   // const bool is<bool>() const | ||||
|   // bool is<bool>() const | ||||
|   template <typename T> | ||||
|   const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value, | ||||
|                                       bool>::type | ||||
|   typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value, bool>::type | ||||
|   is() const { | ||||
|     return isBoolean(); | ||||
|     return variantIsBoolean(); | ||||
|   } | ||||
|   // | ||||
|   // bool is<const char*>() const; | ||||
| @@ -277,7 +276,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|                                     TypeTraits::IsSame<T, char *>::value, | ||||
|                                 bool>::type | ||||
|   is() const { | ||||
|     return isString(); | ||||
|     return variantIsString(); | ||||
|   } | ||||
|   // | ||||
|   // bool is<JsonArray> const; | ||||
| @@ -291,7 +290,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|           JsonArray>::value, | ||||
|       bool>::type | ||||
|   is() const { | ||||
|     return isArray(); | ||||
|     return variantIsArray(); | ||||
|   } | ||||
|   // | ||||
|   // bool is<JsonObject> const; | ||||
| @@ -305,7 +304,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|           JsonObject>::value, | ||||
|       bool>::type | ||||
|   is() const { | ||||
|     return isObject(); | ||||
|     return variantIsObject(); | ||||
|   } | ||||
|  | ||||
|   // Returns true if the variant has a value | ||||
| @@ -314,27 +313,23 @@ class JsonVariant : public JsonVariantBase<JsonVariant> { | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   // It's not allowed to store a char | ||||
|   template <typename T> | ||||
|   JsonVariant(T value, typename TypeTraits::EnableIf< | ||||
|                            TypeTraits::IsSame<T, char>::value>::type * = 0); | ||||
|  | ||||
|   JsonArray &variantAsArray() const; | ||||
|   JsonObject &variantAsObject() const; | ||||
|   const char *variantAsString() const; | ||||
|   Internals::JsonFloat variantAsFloat() const; | ||||
|   Internals::JsonInteger variantAsInteger() const; | ||||
|   Internals::JsonUInt asUnsignedInteger() const; | ||||
|   bool isBoolean() const; | ||||
|   bool isFloat() const; | ||||
|   bool isInteger() const; | ||||
|   bool isArray() const { | ||||
|   template <typename T> | ||||
|   T variantAsFloat() const; | ||||
|   template <typename T> | ||||
|   T variantAsInteger() const; | ||||
|   bool variantIsBoolean() const; | ||||
|   bool variantIsFloat() const; | ||||
|   bool variantIsInteger() const; | ||||
|   bool variantIsArray() const { | ||||
|     return _type == Internals::JSON_ARRAY; | ||||
|   } | ||||
|   bool isObject() const { | ||||
|   bool variantIsObject() const { | ||||
|     return _type == Internals::JSON_OBJECT; | ||||
|   } | ||||
|   bool isString() const { | ||||
|   bool variantIsString() const { | ||||
|     return _type == Internals::JSON_STRING || | ||||
|            (_type == Internals::JSON_UNPARSED && _content.asString && | ||||
|             !strcmp("null", _content.asString)); | ||||
|   | ||||
| @@ -12,11 +12,10 @@ | ||||
| #include "JsonObject.hpp" | ||||
| #include "JsonVariant.hpp" | ||||
| #include "Polyfills/isFloat.hpp" | ||||
| #include "Polyfills/isInteger.hpp" | ||||
| #include "Polyfills/parseFloat.hpp" | ||||
| #include "Polyfills/parseInteger.hpp" | ||||
|  | ||||
| #include <errno.h>   // for errno | ||||
| #include <stdlib.h>  // for strtol, strtod | ||||
| #include <string.h>  // for strcmp | ||||
|  | ||||
| namespace ArduinoJson { | ||||
| @@ -49,42 +48,24 @@ inline JsonObject &JsonVariant::variantAsObject() const { | ||||
|   return JsonObject::invalid(); | ||||
| } | ||||
|  | ||||
| inline Internals::JsonInteger JsonVariant::variantAsInteger() const { | ||||
| template <typename T> | ||||
| inline T JsonVariant::variantAsInteger() const { | ||||
|   using namespace Internals; | ||||
|   switch (_type) { | ||||
|     case JSON_UNDEFINED: | ||||
|       return 0; | ||||
|     case JSON_POSITIVE_INTEGER: | ||||
|     case JSON_BOOLEAN: | ||||
|       return _content.asInteger; | ||||
|       return static_cast<T>(_content.asInteger); | ||||
|     case JSON_NEGATIVE_INTEGER: | ||||
|       return -static_cast<JsonInteger>(_content.asInteger); | ||||
|       return static_cast<T>(_content.asInteger * -1); | ||||
|     case JSON_STRING: | ||||
|     case JSON_UNPARSED: | ||||
|       if (!_content.asString) return 0; | ||||
|       if (!strcmp("true", _content.asString)) return 1; | ||||
|       return Polyfills::parseInteger<JsonInteger>(_content.asString); | ||||
|       return Polyfills::parseInteger<T>(_content.asString); | ||||
|     default: | ||||
|       return static_cast<JsonInteger>(_content.asFloat); | ||||
|   } | ||||
| } | ||||
|  | ||||
| inline Internals::JsonUInt JsonVariant::asUnsignedInteger() const { | ||||
|   using namespace Internals; | ||||
|   switch (_type) { | ||||
|     case JSON_UNDEFINED: | ||||
|       return 0; | ||||
|     case JSON_POSITIVE_INTEGER: | ||||
|     case JSON_BOOLEAN: | ||||
|     case JSON_NEGATIVE_INTEGER: | ||||
|       return _content.asInteger; | ||||
|     case JSON_STRING: | ||||
|     case JSON_UNPARSED: | ||||
|       if (!_content.asString) return 0; | ||||
|       if (!strcmp("true", _content.asString)) return 1; | ||||
|       return Polyfills::parseInteger<JsonUInt>(_content.asString); | ||||
|     default: | ||||
|       return static_cast<JsonUInt>(_content.asFloat); | ||||
|       return static_cast<T>(_content.asFloat); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -97,27 +78,26 @@ inline const char *JsonVariant::variantAsString() const { | ||||
|   return NULL; | ||||
| } | ||||
|  | ||||
| inline Internals::JsonFloat JsonVariant::variantAsFloat() const { | ||||
| template <typename T> | ||||
| inline T JsonVariant::variantAsFloat() const { | ||||
|   using namespace Internals; | ||||
|   switch (_type) { | ||||
|     case JSON_UNDEFINED: | ||||
|       return 0; | ||||
|     case JSON_POSITIVE_INTEGER: | ||||
|     case JSON_BOOLEAN: | ||||
|       return static_cast<JsonFloat>(_content.asInteger); | ||||
|       return static_cast<T>(_content.asInteger); | ||||
|     case JSON_NEGATIVE_INTEGER: | ||||
|       return -static_cast<JsonFloat>(_content.asInteger); | ||||
|       return -static_cast<T>(_content.asInteger); | ||||
|     case JSON_STRING: | ||||
|     case JSON_UNPARSED: | ||||
|       return _content.asString | ||||
|                  ? Polyfills::parseFloat<JsonFloat>(_content.asString) | ||||
|                  : 0; | ||||
|       return Polyfills::parseFloat<T>(_content.asString); | ||||
|     default: | ||||
|       return _content.asFloat; | ||||
|       return static_cast<T>(_content.asFloat); | ||||
|   } | ||||
| } | ||||
|  | ||||
| inline bool JsonVariant::isBoolean() const { | ||||
| inline bool JsonVariant::variantIsBoolean() const { | ||||
|   using namespace Internals; | ||||
|   if (_type == JSON_BOOLEAN) return true; | ||||
|  | ||||
| @@ -127,27 +107,18 @@ inline bool JsonVariant::isBoolean() const { | ||||
|          !strcmp(_content.asString, "false"); | ||||
| } | ||||
|  | ||||
| inline bool JsonVariant::isInteger() const { | ||||
| inline bool JsonVariant::variantIsInteger() const { | ||||
|   using namespace Internals; | ||||
|   if (_type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER) | ||||
|     return true; | ||||
|  | ||||
|   if (_type != JSON_UNPARSED || _content.asString == NULL) return false; | ||||
|  | ||||
|   char *end; | ||||
|   errno = 0; | ||||
|   strtol(_content.asString, &end, 10); | ||||
|  | ||||
|   return *end == '\0' && errno == 0; | ||||
|   return _type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER || | ||||
|          (_type == JSON_UNPARSED && Polyfills::isInteger(_content.asString)); | ||||
| } | ||||
|  | ||||
| inline bool JsonVariant::isFloat() const { | ||||
| inline bool JsonVariant::variantIsFloat() const { | ||||
|   using namespace Internals; | ||||
|   if (_type >= JSON_FLOAT_0_DECIMALS) return true; | ||||
|  | ||||
|   if (_type != JSON_UNPARSED || _content.asString == NULL) return false; | ||||
|  | ||||
|   return Polyfills::isFloat(_content.asString); | ||||
|   return _type >= JSON_FLOAT_0_DECIMALS || | ||||
|          (_type == JSON_UNPARSED && Polyfills::isFloat(_content.asString)); | ||||
| } | ||||
|  | ||||
| #if ARDUINOJSON_ENABLE_STD_STREAM | ||||
|   | ||||
| @@ -8,12 +8,13 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "./ctype.hpp" | ||||
| #include "./math.hpp" | ||||
|  | ||||
| namespace ArduinoJson { | ||||
| namespace Polyfills { | ||||
|  | ||||
| inline bool isFloat(const char* s) { | ||||
|   if (!s) return false; | ||||
|  | ||||
|   if (!strcmp(s, "NaN")) return true; | ||||
|   if (issign(*s)) s++; | ||||
|   if (!strcmp(s, "Infinity")) return true; | ||||
|   | ||||
							
								
								
									
										22
									
								
								include/ArduinoJson/Polyfills/isInteger.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								include/ArduinoJson/Polyfills/isInteger.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| // Copyright Benoit Blanchon 2014-2017 | ||||
| // MIT License | ||||
| // | ||||
| // Arduino JSON library | ||||
| // https://github.com/bblanchon/ArduinoJson | ||||
| // If you like this project, please add a star! | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "./ctype.hpp" | ||||
|  | ||||
| namespace ArduinoJson { | ||||
| namespace Polyfills { | ||||
|  | ||||
| inline bool isInteger(const char* s) { | ||||
|   if (!s) return false; | ||||
|   if (issign(*s)) s++; | ||||
|   while (isdigit(*s)) s++; | ||||
|   return *s == '\0'; | ||||
| } | ||||
| } | ||||
| } | ||||
| @@ -20,6 +20,8 @@ inline T parseFloat(const char* s) { | ||||
|   typedef typename traits::mantissa_type mantissa_t; | ||||
|   typedef typename traits::exponent_type exponent_t; | ||||
|  | ||||
|   if (!s) return 0; | ||||
|  | ||||
|   bool negative_result = false; | ||||
|   switch (*s) { | ||||
|     case '-': | ||||
|   | ||||
| @@ -9,48 +9,32 @@ | ||||
|  | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include "../Configuration.hpp" | ||||
| #include "./ctype.hpp" | ||||
|  | ||||
| namespace ArduinoJson { | ||||
| namespace Polyfills { | ||||
| template <typename T> | ||||
| T parseInteger(const char *s); | ||||
| T parseInteger(const char *s) { | ||||
|   if (!s) return 0; | ||||
|  | ||||
| template <> | ||||
| inline long parseInteger<long>(const char *s) { | ||||
|   return ::strtol(s, NULL, 10); | ||||
| } | ||||
|   T result = 0; | ||||
|   bool negative_result = false; | ||||
|  | ||||
| template <> | ||||
| inline unsigned long parseInteger<unsigned long>(const char *s) { | ||||
|   return ::strtoul(s, NULL, 10); | ||||
| } | ||||
|   switch (*s) { | ||||
|     case '-': | ||||
|       negative_result = true; | ||||
|     case '+': | ||||
|       s++; | ||||
|       break; | ||||
|   } | ||||
|  | ||||
| template <> | ||||
| inline int parseInteger<int>(const char *s) { | ||||
|   return ::atoi(s); | ||||
| } | ||||
|   while (isdigit(*s)) { | ||||
|     result = static_cast<T>(result * 10 + (*s - '0')); | ||||
|     s++; | ||||
|   } | ||||
|  | ||||
| #if ARDUINOJSON_USE_LONG_LONG | ||||
| template <> | ||||
| inline long long parseInteger<long long>(const char *s) { | ||||
|   return ::strtoll(s, NULL, 10); | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline unsigned long long parseInteger<unsigned long long>(const char *s) { | ||||
|   return ::strtoull(s, NULL, 10); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #if ARDUINOJSON_USE_INT64 | ||||
| template <> | ||||
| inline __int64 parseInteger<__int64>(const char *s) { | ||||
|   return ::_strtoi64(s, NULL, 10); | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline unsigned __int64 parseInteger<unsigned __int64>(const char *s) { | ||||
|   return ::_strtoui64(s, NULL, 10); | ||||
| } | ||||
| #endif | ||||
|   return negative_result ? static_cast<T>(result*-1) : result; | ||||
| } | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -19,8 +19,8 @@ template <typename T> | ||||
| struct IsIntegral { | ||||
|   static const bool value = TypeTraits::IsSignedIntegral<T>::value || | ||||
|                             TypeTraits::IsUnsignedIntegral<T>::value || | ||||
|                             TypeTraits::IsSame<T, char>::value || | ||||
|                             TypeTraits::IsSame<T, bool>::value; | ||||
|                             TypeTraits::IsSame<T, char>::value; | ||||
|   // CAUTION: differs from std::is_integral as it doesn't include bool | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
|   | ||||
| @@ -1,37 +0,0 @@ | ||||
| // Copyright Benoit Blanchon 2014-2017 | ||||
| // MIT License | ||||
| // | ||||
| // Arduino JSON library | ||||
| // https://github.com/bblanchon/ArduinoJson | ||||
| // If you like this project, please add a star! | ||||
|  | ||||
| #include <gtest/gtest.h> | ||||
| #include <limits.h>  // for LONG_MAX | ||||
|  | ||||
| #define ARDUINOJSON_USE_LONG_LONG 0 | ||||
| #define ARDUINOJSON_USE_INT64 0 | ||||
| #include <ArduinoJson.h> | ||||
|  | ||||
| #define SUITE Issue90 | ||||
|  | ||||
| static const char* superLong = | ||||
|     "12345678901234567890123456789012345678901234567890123456789012345678901234" | ||||
|     "5678901234567890123456789012345678901234567890123456789012345678901234567"; | ||||
|  | ||||
| static const JsonVariant variant = RawJson(superLong); | ||||
|  | ||||
| TEST(SUITE, IsNotALong) { | ||||
|   ASSERT_FALSE(variant.is<long>()); | ||||
| } | ||||
|  | ||||
| TEST(SUITE, AsLong) { | ||||
|   ASSERT_EQ(LONG_MAX, variant.as<long>()); | ||||
| } | ||||
|  | ||||
| TEST(SUITE, IsAString) { | ||||
|   ASSERT_FALSE(variant.is<const char*>()); | ||||
| } | ||||
|  | ||||
| TEST(SUITE, AsString) { | ||||
|   ASSERT_STREQ(superLong, variant.as<const char*>()); | ||||
| } | ||||
| @@ -63,6 +63,9 @@ TEST_F(JsonVariant_Storage_Tests, Double) { | ||||
| TEST_F(JsonVariant_Storage_Tests, Float) { | ||||
|   testNumericType<float>(); | ||||
| } | ||||
| TEST_F(JsonVariant_Storage_Tests, Char) { | ||||
|   testNumericType<char>(); | ||||
| } | ||||
| TEST_F(JsonVariant_Storage_Tests, SChar) { | ||||
|   testNumericType<signed char>(); | ||||
| } | ||||
|   | ||||
| @@ -18,6 +18,10 @@ struct Polyfills_IsFloat_Tests : testing::Test { | ||||
| }; | ||||
| #define TEST_(X) TEST_F(Polyfills_IsFloat_Tests, X) | ||||
|  | ||||
| TEST_(Null) { | ||||
|   check(false, NULL); | ||||
| } | ||||
|  | ||||
| TEST_(NoExponent) { | ||||
|   check(true, "3.14"); | ||||
|   check(true, "-3.14"); | ||||
|   | ||||
							
								
								
									
										45
									
								
								test/Polyfills_IsInteger_Tests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								test/Polyfills_IsInteger_Tests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| // Copyright Benoit Blanchon 2014-2017 | ||||
| // MIT License | ||||
| // | ||||
| // Arduino JSON library | ||||
| // https://github.com/bblanchon/ArduinoJson | ||||
| // If you like this project, please add a star! | ||||
|  | ||||
| #include <gtest/gtest.h> | ||||
| #include <ArduinoJson/Polyfills/isInteger.hpp> | ||||
|  | ||||
| using namespace ArduinoJson::Polyfills; | ||||
|  | ||||
| struct Polyfills_IsInteger_Tests : testing::Test { | ||||
|   void check(bool expected, const char* input) { | ||||
|     bool actual = isInteger(input); | ||||
|     EXPECT_EQ(expected, actual) << input; | ||||
|   } | ||||
| }; | ||||
| #define TEST_(X) TEST_F(Polyfills_IsInteger_Tests, X) | ||||
|  | ||||
| TEST_(Null) { | ||||
|   check(false, NULL); | ||||
| } | ||||
|  | ||||
| TEST_(FloatNotInteger) { | ||||
|   check(false, "3.14"); | ||||
|   check(false, "-3.14"); | ||||
|   check(false, "+3.14"); | ||||
| } | ||||
|  | ||||
| TEST_(Spaces) { | ||||
|   check(false, "42 "); | ||||
|   check(false, " 42"); | ||||
| } | ||||
|  | ||||
| TEST_(Valid) { | ||||
|   check(true, "42"); | ||||
|   check(true, "-42"); | ||||
|   check(true, "+42"); | ||||
| } | ||||
|  | ||||
| TEST_(ExtraSign) { | ||||
|   check(false, "--42"); | ||||
|   check(false, "++42"); | ||||
| } | ||||
| @@ -54,6 +54,14 @@ struct Polyfills_ParseFloat_Double_Tests : testing::Test { | ||||
| }; | ||||
| #define TEST_DOUBLE(X) TEST_F(Polyfills_ParseFloat_Double_Tests, X) | ||||
|  | ||||
| TEST_DOUBLE(Null) { | ||||
|   check(NULL, 0); | ||||
| } | ||||
|  | ||||
| TEST_FLOAT(Null) { | ||||
|   check(NULL, 0); | ||||
| } | ||||
|  | ||||
| TEST_DOUBLE(Short_NoExponent) { | ||||
|   check("3.14", 3.14); | ||||
|   check("-3.14", -3.14); | ||||
|   | ||||
							
								
								
									
										79
									
								
								test/Polyfills_ParseInteger_Tests.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								test/Polyfills_ParseInteger_Tests.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| // Copyright Benoit Blanchon 2014-2017 | ||||
| // MIT License | ||||
| // | ||||
| // Arduino JSON library | ||||
| // https://github.com/bblanchon/ArduinoJson | ||||
| // If you like this project, please add a star! | ||||
|  | ||||
| #include <gtest/gtest.h> | ||||
| #include <stdint.h> | ||||
| #include <ArduinoJson/Polyfills/parseInteger.hpp> | ||||
|  | ||||
| using namespace ArduinoJson::Polyfills; | ||||
|  | ||||
| struct Polyfills_ParseInteger_Tests : testing::Test { | ||||
|   template <typename T> | ||||
|   void check(const char* input, T expected) { | ||||
|     T actual = parseInteger<T>(input); | ||||
|     EXPECT_EQ(expected, actual) << input; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| #define TEST_(X) TEST_F(Polyfills_ParseInteger_Tests, X) | ||||
|  | ||||
| TEST_(int8_t) { | ||||
|   check<int8_t>("-128", -128); | ||||
|   check<int8_t>("127", 127); | ||||
|   check<int8_t>("+127", 127); | ||||
|   check<int8_t>("3.14", 3); | ||||
|   // check<int8_t>(" 42", 0); | ||||
|   check<int8_t>("x42", 0); | ||||
|   check<int8_t>("128", -128); | ||||
|   check<int8_t>("-129", 127); | ||||
|   check<int8_t>(NULL, 0); | ||||
| } | ||||
|  | ||||
| TEST_(int16_t) { | ||||
|   check<int16_t>("-32768", -32768); | ||||
|   check<int16_t>("32767", 32767); | ||||
|   check<int16_t>("+32767", 32767); | ||||
|   check<int16_t>("3.14", 3); | ||||
|   // check<int16_t>(" 42", 0); | ||||
|   check<int16_t>("x42", 0); | ||||
|   check<int16_t>("-32769", 32767); | ||||
|   check<int16_t>("32768", -32768); | ||||
|   check<int16_t>(NULL, 0); | ||||
| } | ||||
|  | ||||
| TEST_(int32_t) { | ||||
|   check<int32_t>("-2147483648", (-2147483647 - 1)); | ||||
|   check<int32_t>("2147483647", 2147483647); | ||||
|   check<int32_t>("+2147483647", 2147483647); | ||||
|   check<int32_t>("3.14", 3); | ||||
|   // check<int32_t>(" 42", 0); | ||||
|   check<int32_t>("x42", 0); | ||||
|   check<int32_t>("-2147483649", 2147483647); | ||||
|   check<int32_t>("2147483648", (-2147483647 - 1)); | ||||
| } | ||||
|  | ||||
| TEST_(uint8_t) { | ||||
|   check<uint8_t>("0", 0); | ||||
|   check<uint8_t>("255", 255); | ||||
|   check<uint8_t>("+255", 255); | ||||
|   check<uint8_t>("3.14", 3); | ||||
|   // check<uint8_t>(" 42", 0); | ||||
|   check<uint8_t>("x42", 0); | ||||
|   check<uint8_t>("-1", 255); | ||||
|   check<uint8_t>("256", 0); | ||||
| } | ||||
|  | ||||
| TEST_(uint16_t) { | ||||
|   check<uint16_t>("0", 0); | ||||
|   check<uint16_t>("65535", 65535); | ||||
|   check<uint16_t>("+65535", 65535); | ||||
|   check<uint16_t>("3.14", 3); | ||||
|   // check<uint16_t>(" 42", 0); | ||||
|   check<uint16_t>("x42", 0); | ||||
|   check<uint16_t>("-1", 65535); | ||||
|   check<uint16_t>("65536", 0); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user