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