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 `strtod()` (issue #453)
|
||||||
|
* Added custom implementation of `strtol()` (issue #465)
|
||||||
|
* `char` is now treated as an integral type (issue #337, #370)
|
||||||
|
|
||||||
v5.8.3
|
v5.8.3
|
||||||
------
|
------
|
||||||
|
@ -70,13 +70,15 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a JsonVariant containing an integer value.
|
// Create a JsonVariant containing an integer value.
|
||||||
|
// JsonVariant(char)
|
||||||
// JsonVariant(signed short)
|
// JsonVariant(signed short)
|
||||||
// JsonVariant(signed int)
|
// JsonVariant(signed int)
|
||||||
// JsonVariant(signed long)
|
// JsonVariant(signed long)
|
||||||
|
// JsonVariant(signed char)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
JsonVariant(T value,
|
JsonVariant(T value, typename TypeTraits::EnableIf<
|
||||||
typename TypeTraits::EnableIf<
|
TypeTraits::IsSignedIntegral<T>::value ||
|
||||||
TypeTraits::IsSignedIntegral<T>::value>::type * = 0) {
|
TypeTraits::IsSame<T, char>::value>::type * = 0) {
|
||||||
using namespace Internals;
|
using namespace Internals;
|
||||||
if (value >= 0) {
|
if (value >= 0) {
|
||||||
_type = JSON_POSITIVE_INTEGER;
|
_type = JSON_POSITIVE_INTEGER;
|
||||||
@ -129,24 +131,26 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
|||||||
|
|
||||||
// Get the variant as the specified type.
|
// Get the variant as the specified type.
|
||||||
//
|
//
|
||||||
// short as<signed short>() const;
|
// char as<char>() const;
|
||||||
// int as<signed int>() const;
|
// signed char as<signed char>() const;
|
||||||
// long as<signed long>() 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>
|
template <typename T>
|
||||||
const typename TypeTraits::EnableIf<TypeTraits::IsSignedIntegral<T>::value,
|
const typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value, T>::type
|
||||||
T>::type
|
|
||||||
as() const {
|
as() const {
|
||||||
return static_cast<T>(variantAsInteger());
|
return variantAsInteger<T>();
|
||||||
}
|
}
|
||||||
//
|
// bool as<bool>() const
|
||||||
// short as<unsigned short>() const;
|
|
||||||
// int as<unsigned int>() const;
|
|
||||||
// long as<unsigned long>() const;
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const typename TypeTraits::EnableIf<TypeTraits::IsUnsignedIntegral<T>::value,
|
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value,
|
||||||
T>::type
|
T>::type
|
||||||
as() const {
|
as() const {
|
||||||
return static_cast<T>(asUnsignedInteger());
|
return variantAsInteger<int>() != 0;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// double as<double>() const;
|
// double as<double>() const;
|
||||||
@ -155,7 +159,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
|||||||
const typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
|
const typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
|
||||||
T>::type
|
T>::type
|
||||||
as() const {
|
as() const {
|
||||||
return static_cast<T>(variantAsFloat());
|
return variantAsFloat<T>();
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// const char* as<const char*>() const;
|
// const char* as<const char*>() const;
|
||||||
@ -180,14 +184,6 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
|||||||
return s;
|
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;
|
||||||
// JsonArray& as<JsonArray&> const;
|
// JsonArray& as<JsonArray&> const;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -242,32 +238,35 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
|||||||
// Tells weither the variant has the specified type.
|
// Tells weither the variant has the specified type.
|
||||||
// Returns true if the variant has type type T, false otherwise.
|
// Returns true if the variant has type type T, false otherwise.
|
||||||
//
|
//
|
||||||
// short as<short>() const;
|
// bool is<char>() const;
|
||||||
// int as<int>() const;
|
// bool is<signed char>() const;
|
||||||
// long as<long>() 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>
|
template <typename T>
|
||||||
const typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value &&
|
typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value, bool>::type
|
||||||
!TypeTraits::IsSame<T, bool>::value,
|
|
||||||
bool>::type
|
|
||||||
is() const {
|
is() const {
|
||||||
return isInteger();
|
return variantIsInteger();
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// double is<double>() const;
|
// bool is<double>() const;
|
||||||
// float is<float>() const;
|
// bool is<float>() const;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
|
typename TypeTraits::EnableIf<TypeTraits::IsFloatingPoint<T>::value,
|
||||||
bool>::type
|
bool>::type
|
||||||
is() const {
|
is() const {
|
||||||
return isFloat();
|
return variantIsFloat();
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// const bool is<bool>() const
|
// bool is<bool>() const
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value,
|
typename TypeTraits::EnableIf<TypeTraits::IsSame<T, bool>::value, bool>::type
|
||||||
bool>::type
|
|
||||||
is() const {
|
is() const {
|
||||||
return isBoolean();
|
return variantIsBoolean();
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// bool is<const char*>() const;
|
// bool is<const char*>() const;
|
||||||
@ -277,7 +276,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
|||||||
TypeTraits::IsSame<T, char *>::value,
|
TypeTraits::IsSame<T, char *>::value,
|
||||||
bool>::type
|
bool>::type
|
||||||
is() const {
|
is() const {
|
||||||
return isString();
|
return variantIsString();
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// bool is<JsonArray> const;
|
// bool is<JsonArray> const;
|
||||||
@ -291,7 +290,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
|||||||
JsonArray>::value,
|
JsonArray>::value,
|
||||||
bool>::type
|
bool>::type
|
||||||
is() const {
|
is() const {
|
||||||
return isArray();
|
return variantIsArray();
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// bool is<JsonObject> const;
|
// bool is<JsonObject> const;
|
||||||
@ -305,7 +304,7 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
|||||||
JsonObject>::value,
|
JsonObject>::value,
|
||||||
bool>::type
|
bool>::type
|
||||||
is() const {
|
is() const {
|
||||||
return isObject();
|
return variantIsObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if the variant has a value
|
// Returns true if the variant has a value
|
||||||
@ -314,27 +313,23 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
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;
|
JsonArray &variantAsArray() const;
|
||||||
JsonObject &variantAsObject() const;
|
JsonObject &variantAsObject() const;
|
||||||
const char *variantAsString() const;
|
const char *variantAsString() const;
|
||||||
Internals::JsonFloat variantAsFloat() const;
|
template <typename T>
|
||||||
Internals::JsonInteger variantAsInteger() const;
|
T variantAsFloat() const;
|
||||||
Internals::JsonUInt asUnsignedInteger() const;
|
template <typename T>
|
||||||
bool isBoolean() const;
|
T variantAsInteger() const;
|
||||||
bool isFloat() const;
|
bool variantIsBoolean() const;
|
||||||
bool isInteger() const;
|
bool variantIsFloat() const;
|
||||||
bool isArray() const {
|
bool variantIsInteger() const;
|
||||||
|
bool variantIsArray() const {
|
||||||
return _type == Internals::JSON_ARRAY;
|
return _type == Internals::JSON_ARRAY;
|
||||||
}
|
}
|
||||||
bool isObject() const {
|
bool variantIsObject() const {
|
||||||
return _type == Internals::JSON_OBJECT;
|
return _type == Internals::JSON_OBJECT;
|
||||||
}
|
}
|
||||||
bool isString() const {
|
bool variantIsString() const {
|
||||||
return _type == Internals::JSON_STRING ||
|
return _type == Internals::JSON_STRING ||
|
||||||
(_type == Internals::JSON_UNPARSED && _content.asString &&
|
(_type == Internals::JSON_UNPARSED && _content.asString &&
|
||||||
!strcmp("null", _content.asString));
|
!strcmp("null", _content.asString));
|
||||||
|
@ -12,11 +12,10 @@
|
|||||||
#include "JsonObject.hpp"
|
#include "JsonObject.hpp"
|
||||||
#include "JsonVariant.hpp"
|
#include "JsonVariant.hpp"
|
||||||
#include "Polyfills/isFloat.hpp"
|
#include "Polyfills/isFloat.hpp"
|
||||||
|
#include "Polyfills/isInteger.hpp"
|
||||||
#include "Polyfills/parseFloat.hpp"
|
#include "Polyfills/parseFloat.hpp"
|
||||||
#include "Polyfills/parseInteger.hpp"
|
#include "Polyfills/parseInteger.hpp"
|
||||||
|
|
||||||
#include <errno.h> // for errno
|
|
||||||
#include <stdlib.h> // for strtol, strtod
|
|
||||||
#include <string.h> // for strcmp
|
#include <string.h> // for strcmp
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
@ -49,42 +48,24 @@ inline JsonObject &JsonVariant::variantAsObject() const {
|
|||||||
return JsonObject::invalid();
|
return JsonObject::invalid();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Internals::JsonInteger JsonVariant::variantAsInteger() const {
|
template <typename T>
|
||||||
|
inline T JsonVariant::variantAsInteger() const {
|
||||||
using namespace Internals;
|
using namespace Internals;
|
||||||
switch (_type) {
|
switch (_type) {
|
||||||
case JSON_UNDEFINED:
|
case JSON_UNDEFINED:
|
||||||
return 0;
|
return 0;
|
||||||
case JSON_POSITIVE_INTEGER:
|
case JSON_POSITIVE_INTEGER:
|
||||||
case JSON_BOOLEAN:
|
case JSON_BOOLEAN:
|
||||||
return _content.asInteger;
|
return static_cast<T>(_content.asInteger);
|
||||||
case JSON_NEGATIVE_INTEGER:
|
case JSON_NEGATIVE_INTEGER:
|
||||||
return -static_cast<JsonInteger>(_content.asInteger);
|
return static_cast<T>(_content.asInteger * -1);
|
||||||
case JSON_STRING:
|
case JSON_STRING:
|
||||||
case JSON_UNPARSED:
|
case JSON_UNPARSED:
|
||||||
if (!_content.asString) return 0;
|
if (!_content.asString) return 0;
|
||||||
if (!strcmp("true", _content.asString)) return 1;
|
if (!strcmp("true", _content.asString)) return 1;
|
||||||
return Polyfills::parseInteger<JsonInteger>(_content.asString);
|
return Polyfills::parseInteger<T>(_content.asString);
|
||||||
default:
|
default:
|
||||||
return static_cast<JsonInteger>(_content.asFloat);
|
return static_cast<T>(_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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,27 +78,26 @@ inline const char *JsonVariant::variantAsString() const {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Internals::JsonFloat JsonVariant::variantAsFloat() const {
|
template <typename T>
|
||||||
|
inline T JsonVariant::variantAsFloat() const {
|
||||||
using namespace Internals;
|
using namespace Internals;
|
||||||
switch (_type) {
|
switch (_type) {
|
||||||
case JSON_UNDEFINED:
|
case JSON_UNDEFINED:
|
||||||
return 0;
|
return 0;
|
||||||
case JSON_POSITIVE_INTEGER:
|
case JSON_POSITIVE_INTEGER:
|
||||||
case JSON_BOOLEAN:
|
case JSON_BOOLEAN:
|
||||||
return static_cast<JsonFloat>(_content.asInteger);
|
return static_cast<T>(_content.asInteger);
|
||||||
case JSON_NEGATIVE_INTEGER:
|
case JSON_NEGATIVE_INTEGER:
|
||||||
return -static_cast<JsonFloat>(_content.asInteger);
|
return -static_cast<T>(_content.asInteger);
|
||||||
case JSON_STRING:
|
case JSON_STRING:
|
||||||
case JSON_UNPARSED:
|
case JSON_UNPARSED:
|
||||||
return _content.asString
|
return Polyfills::parseFloat<T>(_content.asString);
|
||||||
? Polyfills::parseFloat<JsonFloat>(_content.asString)
|
|
||||||
: 0;
|
|
||||||
default:
|
default:
|
||||||
return _content.asFloat;
|
return static_cast<T>(_content.asFloat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool JsonVariant::isBoolean() const {
|
inline bool JsonVariant::variantIsBoolean() const {
|
||||||
using namespace Internals;
|
using namespace Internals;
|
||||||
if (_type == JSON_BOOLEAN) return true;
|
if (_type == JSON_BOOLEAN) return true;
|
||||||
|
|
||||||
@ -127,27 +107,18 @@ inline bool JsonVariant::isBoolean() const {
|
|||||||
!strcmp(_content.asString, "false");
|
!strcmp(_content.asString, "false");
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool JsonVariant::isInteger() const {
|
inline bool JsonVariant::variantIsInteger() const {
|
||||||
using namespace Internals;
|
using namespace Internals;
|
||||||
if (_type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
|
return _type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER ||
|
||||||
|
(_type == JSON_UNPARSED && Polyfills::isInteger(_content.asString));
|
||||||
char *end;
|
|
||||||
errno = 0;
|
|
||||||
strtol(_content.asString, &end, 10);
|
|
||||||
|
|
||||||
return *end == '\0' && errno == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool JsonVariant::isFloat() const {
|
inline bool JsonVariant::variantIsFloat() const {
|
||||||
using namespace Internals;
|
using namespace Internals;
|
||||||
if (_type >= JSON_FLOAT_0_DECIMALS) return true;
|
|
||||||
|
|
||||||
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
|
return _type >= JSON_FLOAT_0_DECIMALS ||
|
||||||
|
(_type == JSON_UNPARSED && Polyfills::isFloat(_content.asString));
|
||||||
return Polyfills::isFloat(_content.asString);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||||
|
@ -8,12 +8,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "./ctype.hpp"
|
#include "./ctype.hpp"
|
||||||
#include "./math.hpp"
|
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
namespace Polyfills {
|
namespace Polyfills {
|
||||||
|
|
||||||
inline bool isFloat(const char* s) {
|
inline bool isFloat(const char* s) {
|
||||||
|
if (!s) return false;
|
||||||
|
|
||||||
if (!strcmp(s, "NaN")) return true;
|
if (!strcmp(s, "NaN")) return true;
|
||||||
if (issign(*s)) s++;
|
if (issign(*s)) s++;
|
||||||
if (!strcmp(s, "Infinity")) return true;
|
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::mantissa_type mantissa_t;
|
||||||
typedef typename traits::exponent_type exponent_t;
|
typedef typename traits::exponent_type exponent_t;
|
||||||
|
|
||||||
|
if (!s) return 0;
|
||||||
|
|
||||||
bool negative_result = false;
|
bool negative_result = false;
|
||||||
switch (*s) {
|
switch (*s) {
|
||||||
case '-':
|
case '-':
|
||||||
|
@ -9,48 +9,32 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "../Configuration.hpp"
|
||||||
|
#include "./ctype.hpp"
|
||||||
|
|
||||||
namespace ArduinoJson {
|
namespace ArduinoJson {
|
||||||
namespace Polyfills {
|
namespace Polyfills {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T parseInteger(const char *s);
|
T parseInteger(const char *s) {
|
||||||
|
if (!s) return 0;
|
||||||
|
|
||||||
template <>
|
T result = 0;
|
||||||
inline long parseInteger<long>(const char *s) {
|
bool negative_result = false;
|
||||||
return ::strtol(s, NULL, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <>
|
switch (*s) {
|
||||||
inline unsigned long parseInteger<unsigned long>(const char *s) {
|
case '-':
|
||||||
return ::strtoul(s, NULL, 10);
|
negative_result = true;
|
||||||
}
|
case '+':
|
||||||
|
s++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
template <>
|
while (isdigit(*s)) {
|
||||||
inline int parseInteger<int>(const char *s) {
|
result = static_cast<T>(result * 10 + (*s - '0'));
|
||||||
return ::atoi(s);
|
s++;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ARDUINOJSON_USE_LONG_LONG
|
return negative_result ? static_cast<T>(result*-1) : result;
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@ template <typename T>
|
|||||||
struct IsIntegral {
|
struct IsIntegral {
|
||||||
static const bool value = TypeTraits::IsSignedIntegral<T>::value ||
|
static const bool value = TypeTraits::IsSignedIntegral<T>::value ||
|
||||||
TypeTraits::IsUnsignedIntegral<T>::value ||
|
TypeTraits::IsUnsignedIntegral<T>::value ||
|
||||||
TypeTraits::IsSame<T, char>::value ||
|
TypeTraits::IsSame<T, char>::value;
|
||||||
TypeTraits::IsSame<T, bool>::value;
|
// CAUTION: differs from std::is_integral as it doesn't include bool
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
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) {
|
TEST_F(JsonVariant_Storage_Tests, Float) {
|
||||||
testNumericType<float>();
|
testNumericType<float>();
|
||||||
}
|
}
|
||||||
|
TEST_F(JsonVariant_Storage_Tests, Char) {
|
||||||
|
testNumericType<char>();
|
||||||
|
}
|
||||||
TEST_F(JsonVariant_Storage_Tests, SChar) {
|
TEST_F(JsonVariant_Storage_Tests, SChar) {
|
||||||
testNumericType<signed char>();
|
testNumericType<signed char>();
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,10 @@ struct Polyfills_IsFloat_Tests : testing::Test {
|
|||||||
};
|
};
|
||||||
#define TEST_(X) TEST_F(Polyfills_IsFloat_Tests, X)
|
#define TEST_(X) TEST_F(Polyfills_IsFloat_Tests, X)
|
||||||
|
|
||||||
|
TEST_(Null) {
|
||||||
|
check(false, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_(NoExponent) {
|
TEST_(NoExponent) {
|
||||||
check(true, "3.14");
|
check(true, "3.14");
|
||||||
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)
|
#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) {
|
TEST_DOUBLE(Short_NoExponent) {
|
||||||
check("3.14", 3.14);
|
check("3.14", 3.14);
|
||||||
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