forked from bblanchon/ArduinoJson
Simplified the implementation of parseNumber()
This commit is contained in:
@ -499,26 +499,12 @@ class JsonDeserializer {
|
||||
return true;
|
||||
}
|
||||
|
||||
ParsedNumber<Float, UInt> num;
|
||||
parseNumber<Float, UInt>(_buffer, num);
|
||||
|
||||
switch (num.type()) {
|
||||
case VALUE_IS_NEGATIVE_INTEGER:
|
||||
result.setNegativeInteger(num.uintValue);
|
||||
return true;
|
||||
|
||||
case VALUE_IS_POSITIVE_INTEGER:
|
||||
result.setPositiveInteger(num.uintValue);
|
||||
return true;
|
||||
|
||||
case VALUE_IS_FLOAT:
|
||||
result.setFloat(num.floatValue);
|
||||
return true;
|
||||
|
||||
default:
|
||||
_error = DeserializationError::InvalidInput;
|
||||
return false;
|
||||
if (!parseNumber(_buffer, result)) {
|
||||
_error = DeserializationError::InvalidInput;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool skipNumericValue() {
|
||||
|
@ -1,20 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
||||
#include <ArduinoJson/Numbers/parseNumber.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename T>
|
||||
inline T parseFloat(const char* s) {
|
||||
// try to reuse the same parameters as JsonDeserializer
|
||||
typedef typename choose_largest<Float, T>::type TFloat;
|
||||
ParsedNumber<TFloat, UInt> value;
|
||||
parseNumber(s, value);
|
||||
return value.template as<T>();
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -1,21 +0,0 @@
|
||||
// ArduinoJson - arduinojson.org
|
||||
// Copyright Benoit Blanchon 2014-2020
|
||||
// MIT License
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
||||
#include <ArduinoJson/Numbers/parseNumber.hpp>
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
template <typename T>
|
||||
T parseInteger(const char *s) {
|
||||
// try to reuse the same parameters as JsonDeserializer
|
||||
typedef typename choose_largest<UInt, typename make_unsigned<T>::type>::type
|
||||
TUInt;
|
||||
ParsedNumber<Float, TUInt> value;
|
||||
parseNumber(s, value);
|
||||
return value.template as<T>();
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
@ -10,59 +10,18 @@
|
||||
#include <ArduinoJson/Polyfills/ctype.hpp>
|
||||
#include <ArduinoJson/Polyfills/math.hpp>
|
||||
#include <ArduinoJson/Polyfills/type_traits.hpp>
|
||||
#include <ArduinoJson/Variant/VariantContent.hpp>
|
||||
#include <ArduinoJson/Variant/VariantAs.hpp>
|
||||
#include <ArduinoJson/Variant/VariantData.hpp>
|
||||
|
||||
namespace ARDUINOJSON_NAMESPACE {
|
||||
|
||||
template <typename TFloat, typename TUInt>
|
||||
struct ParsedNumber {
|
||||
ParsedNumber() : _type(VALUE_IS_NULL) {}
|
||||
|
||||
void setInteger(TUInt value, bool is_negative) {
|
||||
uintValue = value;
|
||||
_type = uint8_t(is_negative ? VALUE_IS_NEGATIVE_INTEGER
|
||||
: VALUE_IS_POSITIVE_INTEGER);
|
||||
}
|
||||
|
||||
void setFloat(TFloat value) {
|
||||
floatValue = value;
|
||||
_type = VALUE_IS_FLOAT;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T as() const {
|
||||
switch (_type) {
|
||||
case VALUE_IS_NEGATIVE_INTEGER:
|
||||
return convertNegativeInteger<T>(uintValue);
|
||||
case VALUE_IS_POSITIVE_INTEGER:
|
||||
return convertPositiveInteger<T>(uintValue);
|
||||
case VALUE_IS_FLOAT:
|
||||
return convertFloat<T>(floatValue);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t type() const {
|
||||
return _type;
|
||||
}
|
||||
|
||||
union {
|
||||
TUInt uintValue;
|
||||
TFloat floatValue;
|
||||
};
|
||||
uint8_t _type;
|
||||
}; // namespace ARDUINOJSON_NAMESPACE
|
||||
|
||||
template <typename A, typename B>
|
||||
struct choose_largest : conditional<(sizeof(A) > sizeof(B)), A, B> {};
|
||||
|
||||
template <typename TFloat, typename TUInt>
|
||||
inline void parseNumber(const char* s, ParsedNumber<TFloat, TUInt>& result) {
|
||||
typedef FloatTraits<TFloat> traits;
|
||||
typedef typename choose_largest<typename traits::mantissa_type, TUInt>::type
|
||||
mantissa_t;
|
||||
typedef typename traits::exponent_type exponent_t;
|
||||
inline bool parseNumber(const char* s, VariantData& result) {
|
||||
typedef FloatTraits<Float> traits;
|
||||
typedef choose_largest<traits::mantissa_type, UInt>::type mantissa_t;
|
||||
typedef traits::exponent_type exponent_t;
|
||||
|
||||
ARDUINOJSON_ASSERT(s != 0);
|
||||
|
||||
@ -80,24 +39,23 @@ inline void parseNumber(const char* s, ParsedNumber<TFloat, TUInt>& result) {
|
||||
#if ARDUINOJSON_ENABLE_NAN
|
||||
if (*s == 'n' || *s == 'N') {
|
||||
result.setFloat(traits::nan());
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if ARDUINOJSON_ENABLE_INFINITY
|
||||
if (*s == 'i' || *s == 'I') {
|
||||
result.setFloat(is_negative ? -traits::inf() : traits::inf());
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!isdigit(*s) && *s != '.')
|
||||
return;
|
||||
return false;
|
||||
|
||||
mantissa_t mantissa = 0;
|
||||
exponent_t exponent_offset = 0;
|
||||
const mantissa_t maxUint = TUInt(-1);
|
||||
const mantissa_t maxUint = UInt(-1);
|
||||
|
||||
while (isdigit(*s)) {
|
||||
uint8_t digit = uint8_t(*s - '0');
|
||||
@ -111,8 +69,11 @@ inline void parseNumber(const char* s, ParsedNumber<TFloat, TUInt>& result) {
|
||||
}
|
||||
|
||||
if (*s == '\0') {
|
||||
result.setInteger(TUInt(mantissa), is_negative);
|
||||
return;
|
||||
if (is_negative)
|
||||
result.setNegativeInteger(UInt(mantissa));
|
||||
else
|
||||
result.setPositiveInteger(UInt(mantissa));
|
||||
return true;
|
||||
}
|
||||
|
||||
// avoid mantissa overflow
|
||||
@ -156,7 +117,7 @@ inline void parseNumber(const char* s, ParsedNumber<TFloat, TUInt>& result) {
|
||||
result.setFloat(is_negative ? -0.0f : 0.0f);
|
||||
else
|
||||
result.setFloat(is_negative ? -traits::inf() : traits::inf());
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
@ -167,11 +128,20 @@ inline void parseNumber(const char* s, ParsedNumber<TFloat, TUInt>& result) {
|
||||
|
||||
// we should be at the end of the string, otherwise it's an error
|
||||
if (*s != '\0')
|
||||
return;
|
||||
return false;
|
||||
|
||||
TFloat final_result =
|
||||
traits::make_float(static_cast<TFloat>(mantissa), exponent);
|
||||
Float final_result =
|
||||
traits::make_float(static_cast<Float>(mantissa), exponent);
|
||||
|
||||
result.setFloat(is_negative ? -final_result : final_result);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T parseNumber(const char* s) {
|
||||
VariantData value;
|
||||
value.init(); // VariantData is a POD, so it has no constructor
|
||||
parseNumber(s, value);
|
||||
return variantAs<T>(&value);
|
||||
}
|
||||
} // namespace ARDUINOJSON_NAMESPACE
|
||||
|
@ -33,6 +33,9 @@ class VariantData {
|
||||
// - no destructor
|
||||
// - no virtual
|
||||
// - no inheritance
|
||||
void init() {
|
||||
_flags = 0;
|
||||
}
|
||||
|
||||
template <typename TVisitor>
|
||||
typename TVisitor::result_type accept(TVisitor &visitor) const {
|
||||
@ -365,11 +368,11 @@ class VariantData {
|
||||
_content.asCollection.movePointers(stringDistance, variantDistance);
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t type() const {
|
||||
return _flags & VALUE_MASK;
|
||||
}
|
||||
|
||||
private:
|
||||
void setType(uint8_t t) {
|
||||
_flags &= KEY_IS_OWNED;
|
||||
_flags |= t;
|
||||
|
@ -4,10 +4,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ArduinoJson/Array/ArrayRef.hpp>
|
||||
#include <ArduinoJson/Configuration.hpp>
|
||||
#include <ArduinoJson/Numbers/convertNumber.hpp>
|
||||
#include <ArduinoJson/Numbers/parseFloat.hpp>
|
||||
#include <ArduinoJson/Numbers/parseInteger.hpp>
|
||||
#include <ArduinoJson/Numbers/parseNumber.hpp>
|
||||
#include <ArduinoJson/Object/ObjectRef.hpp>
|
||||
#include <ArduinoJson/Variant/VariantRef.hpp>
|
||||
|
||||
#include <string.h> // for strcmp
|
||||
@ -24,7 +25,7 @@ inline T VariantData::asIntegral() const {
|
||||
return convertNegativeInteger<T>(_content.asInteger);
|
||||
case VALUE_IS_LINKED_STRING:
|
||||
case VALUE_IS_OWNED_STRING:
|
||||
return parseInteger<T>(_content.asString);
|
||||
return parseNumber<T>(_content.asString);
|
||||
case VALUE_IS_FLOAT:
|
||||
return convertFloat<T>(_content.asFloat);
|
||||
default:
|
||||
@ -58,7 +59,7 @@ inline T VariantData::asFloat() const {
|
||||
return -static_cast<T>(_content.asInteger);
|
||||
case VALUE_IS_LINKED_STRING:
|
||||
case VALUE_IS_OWNED_STRING:
|
||||
return parseFloat<T>(_content.asString);
|
||||
return parseNumber<T>(_content.asString);
|
||||
case VALUE_IS_FLOAT:
|
||||
return static_cast<T>(_content.asFloat);
|
||||
default:
|
||||
|
Reference in New Issue
Block a user