forked from bblanchon/ArduinoJson
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,
|
||||
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;
|
||||
|
||||
switch (*s) {
|
||||
case '-':
|
||||
negative_result = true;
|
||||
case '+':
|
||||
s++;
|
||||
break;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline unsigned long parseInteger<unsigned long>(const char *s) {
|
||||
return ::strtoul(s, NULL, 10);
|
||||
while (isdigit(*s)) {
|
||||
result = static_cast<T>(result * 10 + (*s - '0'));
|
||||
s++;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline int parseInteger<int>(const char *s) {
|
||||
return ::atoi(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