forked from bblanchon/ArduinoJson
Fix unsigned long
printed as signed long
(issue #170)
This commit is contained in:
@ -1,6 +1,11 @@
|
|||||||
ArduinoJson: change log
|
ArduinoJson: change log
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
|
HEAD
|
||||||
|
----
|
||||||
|
|
||||||
|
* Fix `unsigned long` printed as `signed long` (issue #170)
|
||||||
|
|
||||||
v5.2.0
|
v5.2.0
|
||||||
------
|
------
|
||||||
|
|
||||||
|
@ -56,22 +56,16 @@ class Print {
|
|||||||
return print(tmp);
|
return print(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t print(ArduinoJson::Internals::JsonInteger value) {
|
size_t print(ArduinoJson::Internals::JsonUInt value) {
|
||||||
// see http://clc-wiki.net/wiki/K%26R2_solutions:Chapter_3:Exercise_4
|
|
||||||
char buffer[22];
|
char buffer[22];
|
||||||
|
|
||||||
size_t n = 0;
|
|
||||||
if (value < 0) {
|
|
||||||
value = -value;
|
|
||||||
n += write('-');
|
|
||||||
}
|
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
do {
|
do {
|
||||||
ArduinoJson::Internals::JsonInteger digit = value % 10;
|
buffer[i++] = static_cast<char>(value % 10 + '0');
|
||||||
value /= 10;
|
value /= 10;
|
||||||
buffer[i++] = static_cast<char>(digit >= 0 ? '0' + digit : '0' - digit);
|
|
||||||
} while (value);
|
} while (value);
|
||||||
|
|
||||||
|
size_t n = 0;
|
||||||
while (i > 0) {
|
while (i > 0) {
|
||||||
n += write(buffer[--i]);
|
n += write(buffer[--i]);
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,13 @@ namespace Internals {
|
|||||||
|
|
||||||
#if ARDUINOJSON_USE_LONG_LONG
|
#if ARDUINOJSON_USE_LONG_LONG
|
||||||
typedef long long JsonInteger;
|
typedef long long JsonInteger;
|
||||||
|
typedef unsigned long long JsonUInt;
|
||||||
#elif ARDUINOJSON_USE_INT64
|
#elif ARDUINOJSON_USE_INT64
|
||||||
typedef __int64 JsonInteger;
|
typedef __int64 JsonInteger;
|
||||||
|
typedef unsigned _int64 JsonUInt;
|
||||||
#else
|
#else
|
||||||
typedef long JsonInteger;
|
typedef long JsonInteger;
|
||||||
|
typedef unsigned long JsonUInt;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,11 @@ namespace Internals {
|
|||||||
// A union that defines the actual content of a JsonVariant.
|
// A union that defines the actual content of a JsonVariant.
|
||||||
// The enum JsonVariantType determines which member is in use.
|
// The enum JsonVariantType determines which member is in use.
|
||||||
union JsonVariantContent {
|
union JsonVariantContent {
|
||||||
JsonFloat asFloat; // used for double and float
|
JsonFloat asFloat; // used for double and float
|
||||||
JsonInteger asInteger; // used for bool, char, short, int and longs
|
JsonUInt asInteger; // used for bool, char, short, int and longs
|
||||||
const char* asString; // asString can be null
|
const char* asString; // asString can be null
|
||||||
JsonArray* asArray; // asArray cannot be null
|
JsonArray* asArray; // asArray cannot be null
|
||||||
JsonObject* asObject; // asObject cannot be null
|
JsonObject* asObject; // asObject cannot be null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,13 +16,15 @@ namespace Internals {
|
|||||||
// Enumerated type to know the current type of a JsonVariant.
|
// Enumerated type to know the current type of a JsonVariant.
|
||||||
// The value determines which member of JsonVariantContent is used.
|
// The value determines which member of JsonVariantContent is used.
|
||||||
enum JsonVariantType {
|
enum JsonVariantType {
|
||||||
JSON_UNDEFINED, // the JsonVariant has not been initialized
|
JSON_UNDEFINED, // JsonVariant has not been initialized
|
||||||
JSON_UNPARSED, // the JsonVariant contains an unparsed string
|
JSON_UNPARSED, // JsonVariant contains an unparsed string
|
||||||
JSON_STRING, // the JsonVariant stores a const char*
|
JSON_STRING, // JsonVariant stores a const char*
|
||||||
JSON_BOOLEAN, // the JsonVariant stores a bool
|
JSON_BOOLEAN, // JsonVariant stores a bool
|
||||||
JSON_INTEGER, // the JsonVariant stores an integer
|
JSON_POSITIVE_INTEGER, // JsonVariant stores an unsigned long
|
||||||
JSON_ARRAY, // the JsonVariant stores a pointer to a JsonArray
|
JSON_NEGATIVE_INTEGER, // JsonVariant stores an unsigned long that must be
|
||||||
JSON_OBJECT, // the JsonVariant stores a pointer to a JsonObject
|
// negated
|
||||||
|
JSON_ARRAY, // JsonVariant stores a pointer to a JsonArray
|
||||||
|
JSON_OBJECT, // JsonVariant stores a pointer to a JsonObject
|
||||||
|
|
||||||
// The following values are reserved for float values
|
// The following values are reserved for float values
|
||||||
// Multiple values are used for double, depending on the number of decimal
|
// Multiple values are used for double, depending on the number of decimal
|
||||||
|
@ -32,49 +32,47 @@ class JsonWriter {
|
|||||||
// number of bytes written.
|
// number of bytes written.
|
||||||
size_t bytesWritten() const { return _length; }
|
size_t bytesWritten() const { return _length; }
|
||||||
|
|
||||||
void beginArray() { write('['); }
|
void beginArray() { writeRaw('['); }
|
||||||
void endArray() { write(']'); }
|
void endArray() { writeRaw(']'); }
|
||||||
|
|
||||||
void beginObject() { write('{'); }
|
void beginObject() { writeRaw('{'); }
|
||||||
void endObject() { write('}'); }
|
void endObject() { writeRaw('}'); }
|
||||||
|
|
||||||
void writeColon() { write(':'); }
|
void writeColon() { writeRaw(':'); }
|
||||||
void writeComma() { write(','); }
|
void writeComma() { writeRaw(','); }
|
||||||
|
|
||||||
void writeBoolean(bool value) { write(value ? "true" : "false"); }
|
void writeBoolean(bool value) { writeRaw(value ? "true" : "false"); }
|
||||||
|
|
||||||
void writeString(const char *value) {
|
void writeString(const char *value) {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
write("null");
|
writeRaw("null");
|
||||||
} else {
|
} else {
|
||||||
write('\"');
|
writeRaw('\"');
|
||||||
while (*value) writeChar(*value++);
|
while (*value) writeChar(*value++);
|
||||||
write('\"');
|
writeRaw('\"');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeChar(char c) {
|
void writeChar(char c) {
|
||||||
char specialChar = Encoding::escapeChar(c);
|
char specialChar = Encoding::escapeChar(c);
|
||||||
if (specialChar) {
|
if (specialChar) {
|
||||||
write('\\');
|
writeRaw('\\');
|
||||||
write(specialChar);
|
writeRaw(specialChar);
|
||||||
} else {
|
} else {
|
||||||
write(c);
|
writeRaw(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeInteger(JsonInteger value) { _length += _sink.print(value); }
|
void writeInteger(JsonUInt value) { _length += _sink.print(value); }
|
||||||
|
|
||||||
void writeFloat(JsonFloat value, uint8_t decimals) {
|
void writeFloat(JsonFloat value, uint8_t decimals) {
|
||||||
_length += _sink.print(value, decimals);
|
_length += _sink.print(value, decimals);
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeRaw(const char *s) { return write(s); }
|
void writeRaw(const char *s) { _length += _sink.print(s); }
|
||||||
|
void writeRaw(char c) { _length += _sink.write(c); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void write(char c) { _length += _sink.write(c); }
|
|
||||||
FORCE_INLINE void write(const char *s) { _length += _sink.print(s); }
|
|
||||||
|
|
||||||
Print &_sink;
|
Print &_sink;
|
||||||
size_t _length;
|
size_t _length;
|
||||||
|
|
||||||
|
@ -72,8 +72,13 @@ class JsonVariant : public JsonVariantBase<JsonVariant> {
|
|||||||
typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value>::type * =
|
typename TypeTraits::EnableIf<TypeTraits::IsIntegral<T>::value>::type * =
|
||||||
0) {
|
0) {
|
||||||
using namespace Internals;
|
using namespace Internals;
|
||||||
_type = JSON_INTEGER;
|
if (value >= 0) {
|
||||||
_content.asInteger = static_cast<JsonInteger>(value);
|
_type = JSON_POSITIVE_INTEGER;
|
||||||
|
_content.asInteger = static_cast<JsonInteger>(value);
|
||||||
|
} else {
|
||||||
|
_type = JSON_NEGATIVE_INTEGER;
|
||||||
|
_content.asInteger = static_cast<JsonInteger>(-value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a JsonVariant containing a string.
|
// Create a JsonVariant containing a string.
|
||||||
|
@ -47,19 +47,23 @@ inline T JsonVariant::invalid() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline Internals::JsonInteger JsonVariant::asInteger() const {
|
inline Internals::JsonInteger JsonVariant::asInteger() const {
|
||||||
if (_type == Internals::JSON_INTEGER || _type == Internals::JSON_BOOLEAN)
|
using namespace Internals;
|
||||||
return _content.asInteger;
|
switch (_type) {
|
||||||
|
case JSON_UNDEFINED:
|
||||||
if (_type >= Internals::JSON_FLOAT_0_DECIMALS)
|
return 0;
|
||||||
return static_cast<Internals::JsonInteger>(_content.asFloat);
|
case JSON_POSITIVE_INTEGER:
|
||||||
|
case JSON_BOOLEAN:
|
||||||
if ((_type == Internals::JSON_STRING || _type == Internals::JSON_UNPARSED) &&
|
return _content.asInteger;
|
||||||
_content.asString) {
|
case JSON_NEGATIVE_INTEGER:
|
||||||
if (!strcmp("true", _content.asString)) return 1;
|
return -_content.asInteger;
|
||||||
return Internals::parse<Internals::JsonInteger>(_content.asString);
|
case JSON_STRING:
|
||||||
|
case JSON_UNPARSED:
|
||||||
|
if (!_content.asString) return 0;
|
||||||
|
if (!strcmp("true", _content.asString)) return 1;
|
||||||
|
return parse<Internals::JsonInteger>(_content.asString);
|
||||||
|
default:
|
||||||
|
return static_cast<Internals::JsonInteger>(_content.asFloat);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0L;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ARDUINOJSON_ENABLE_STD_STREAM
|
#if ARDUINOJSON_ENABLE_STD_STREAM
|
||||||
|
@ -26,15 +26,20 @@ const char *JsonVariant::asString() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JsonFloat JsonVariant::asFloat() const {
|
JsonFloat JsonVariant::asFloat() const {
|
||||||
if (_type >= JSON_FLOAT_0_DECIMALS) return _content.asFloat;
|
switch (_type) {
|
||||||
|
case JSON_UNDEFINED:
|
||||||
if (_type == JSON_INTEGER || _type == JSON_BOOLEAN)
|
return 0;
|
||||||
return static_cast<JsonFloat>(_content.asInteger);
|
case JSON_POSITIVE_INTEGER:
|
||||||
|
case JSON_BOOLEAN:
|
||||||
if ((_type == JSON_STRING || _type == JSON_UNPARSED) && _content.asString)
|
return static_cast<JsonFloat>(_content.asInteger);
|
||||||
return parse<JsonFloat>(_content.asString);
|
case JSON_NEGATIVE_INTEGER:
|
||||||
|
return -static_cast<JsonFloat>(_content.asInteger);
|
||||||
return 0.0;
|
case JSON_STRING:
|
||||||
|
case JSON_UNPARSED:
|
||||||
|
return _content.asString ? parse<JsonFloat>(_content.asString) : 0;
|
||||||
|
default:
|
||||||
|
return _content.asFloat;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String JsonVariant::toString() const {
|
String JsonVariant::toString() const {
|
||||||
@ -57,7 +62,8 @@ bool JsonVariant::isBoolean() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool JsonVariant::isInteger() const {
|
bool JsonVariant::isInteger() const {
|
||||||
if (_type == JSON_INTEGER) return true;
|
if (_type == JSON_POSITIVE_INTEGER || _type == JSON_NEGATIVE_INTEGER)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
|
if (_type != JSON_UNPARSED || _content.asString == NULL) return false;
|
||||||
|
|
||||||
@ -81,27 +87,39 @@ bool JsonVariant::isFloat() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void JsonVariant::writeTo(JsonWriter &writer) const {
|
void JsonVariant::writeTo(JsonWriter &writer) const {
|
||||||
if (_type == JSON_ARRAY)
|
switch (_type) {
|
||||||
_content.asArray->writeTo(writer);
|
case JSON_UNDEFINED:
|
||||||
|
return;
|
||||||
|
|
||||||
else if (_type == JSON_OBJECT)
|
case JSON_ARRAY:
|
||||||
_content.asObject->writeTo(writer);
|
_content.asArray->writeTo(writer);
|
||||||
|
return;
|
||||||
|
|
||||||
else if (_type == JSON_STRING)
|
case JSON_OBJECT:
|
||||||
writer.writeString(_content.asString);
|
_content.asObject->writeTo(writer);
|
||||||
|
return;
|
||||||
|
|
||||||
else if (_type == JSON_UNPARSED)
|
case JSON_STRING:
|
||||||
writer.writeRaw(_content.asString);
|
writer.writeString(_content.asString);
|
||||||
|
return;
|
||||||
|
|
||||||
else if (_type == JSON_INTEGER)
|
case JSON_UNPARSED:
|
||||||
writer.writeInteger(_content.asInteger);
|
writer.writeRaw(_content.asString);
|
||||||
|
return;
|
||||||
|
|
||||||
else if (_type == JSON_BOOLEAN)
|
case JSON_NEGATIVE_INTEGER:
|
||||||
writer.writeBoolean(_content.asInteger != 0);
|
writer.writeRaw('-');
|
||||||
|
case JSON_POSITIVE_INTEGER:
|
||||||
|
writer.writeInteger(_content.asInteger);
|
||||||
|
return;
|
||||||
|
|
||||||
else if (_type >= JSON_FLOAT_0_DECIMALS) {
|
case JSON_BOOLEAN:
|
||||||
uint8_t decimals = static_cast<uint8_t>(_type - JSON_FLOAT_0_DECIMALS);
|
writer.writeBoolean(_content.asInteger != 0);
|
||||||
writer.writeFloat(_content.asFloat, decimals);
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
uint8_t decimals = static_cast<uint8_t>(_type - JSON_FLOAT_0_DECIMALS);
|
||||||
|
writer.writeFloat(_content.asFloat, decimals);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,6 +125,14 @@ TEST_F(JsonParser_Array_Tests, TwoDoubles) {
|
|||||||
secondElementMustBe(1e2);
|
secondElementMustBe(1e2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(JsonParser_Array_Tests, UnsignedLong) {
|
||||||
|
whenInputIs("[4294967295]");
|
||||||
|
|
||||||
|
parseMustSucceed();
|
||||||
|
sizeMustBe(1);
|
||||||
|
firstElementMustBe(4294967295UL);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(JsonParser_Array_Tests, TwoBooleans) {
|
TEST_F(JsonParser_Array_Tests, TwoBooleans) {
|
||||||
whenInputIs("[true,false]");
|
whenInputIs("[true,false]");
|
||||||
|
|
||||||
|
@ -57,6 +57,11 @@ TEST_F(JsonVariant_PrintTo_Tests, Long) {
|
|||||||
outputMustBe("42");
|
outputMustBe("42");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(JsonVariant_PrintTo_Tests, UnsignedLong) {
|
||||||
|
variant = 4294967295UL;
|
||||||
|
outputMustBe("4294967295");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(JsonVariant_PrintTo_Tests, Char) {
|
TEST_F(JsonVariant_PrintTo_Tests, Char) {
|
||||||
variant = '*';
|
variant = '*';
|
||||||
outputMustBe("42");
|
outputMustBe("42");
|
||||||
@ -82,4 +87,9 @@ TEST_F(JsonVariant_PrintTo_Tests, PositiveInt64) {
|
|||||||
variant = 9223372036854775807;
|
variant = 9223372036854775807;
|
||||||
outputMustBe("9223372036854775807");
|
outputMustBe("9223372036854775807");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(JsonVariant_PrintTo_Tests, UInt64) {
|
||||||
|
variant = 18446744073709551615;
|
||||||
|
outputMustBe("18446744073709551615");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user