mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-29 18:27:37 +02:00
Read MsgPack's 64-bit ints even if ARDUINOJSON_USE_LONG_LONG
is 0
This commit is contained in:
@ -13,6 +13,8 @@ HEAD
|
||||
Note: works only for reading, not for writing
|
||||
* Support `ElementProxy` and `MemberProxy` in `JsonDocument`'s constructor
|
||||
* Don't add partial objects when allocation fails (issue #2081)
|
||||
* Read MsgPack's 64-bit integers even if `ARDUINOJSON_USE_LONG_LONG` is `0`
|
||||
(they are set to `null` if they don't fit in a `long`)
|
||||
|
||||
v7.0.4 (2024-03-12)
|
||||
------
|
||||
|
@ -3,14 +3,40 @@
|
||||
|
||||
#include <catch.hpp>
|
||||
|
||||
#include "Literals.hpp"
|
||||
|
||||
TEST_CASE("ARDUINOJSON_USE_LONG_LONG == 0") {
|
||||
JsonDocument doc;
|
||||
|
||||
doc["A"] = 42;
|
||||
doc["B"] = 84;
|
||||
SECTION("smoke test") {
|
||||
doc["A"] = 42;
|
||||
doc["B"] = 84;
|
||||
|
||||
std::string json;
|
||||
serializeJson(doc, json);
|
||||
std::string json;
|
||||
serializeJson(doc, json);
|
||||
|
||||
REQUIRE(json == "{\"A\":42,\"B\":84}");
|
||||
REQUIRE(json == "{\"A\":42,\"B\":84}");
|
||||
}
|
||||
|
||||
SECTION("deserializeMsgPack()") {
|
||||
SECTION("cf 00 00 00 00 ff ff ff ff") {
|
||||
auto err =
|
||||
deserializeMsgPack(doc, "\xcf\x00\x00\x00\x00\xff\xff\xff\xff"_s);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
REQUIRE(doc.as<uint32_t>() == 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
SECTION("cf 00 00 00 01 00 00 00 00") {
|
||||
auto err =
|
||||
deserializeMsgPack(doc, "\xcf\x00\x00\x00\x01\x00\x00\x00\x00"_s);
|
||||
|
||||
REQUIRE(err == DeserializationError::Ok);
|
||||
#if defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ >= 8
|
||||
REQUIRE(doc.as<JsonInteger>() == 0x100000000);
|
||||
#else
|
||||
REQUIRE(doc.isNull());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +54,14 @@ class MsgPackDeserializer {
|
||||
ARDUINOJSON_ASSERT(variant != 0);
|
||||
}
|
||||
|
||||
if (code >= 0xcc && code <= 0xd3) {
|
||||
auto width = uint8_t(1U << ((code - 0xcc) % 4));
|
||||
if (allowValue)
|
||||
return readInteger(variant, width, code >= 0xd0);
|
||||
else
|
||||
return skipBytes(width);
|
||||
}
|
||||
|
||||
switch (code) {
|
||||
case 0xc0:
|
||||
// already null
|
||||
@ -83,62 +91,6 @@ class MsgPackDeserializer {
|
||||
return readDouble<double>(variant);
|
||||
else
|
||||
return skipBytes(8);
|
||||
|
||||
case 0xcc:
|
||||
if (allowValue)
|
||||
return readInteger<uint8_t>(variant);
|
||||
else
|
||||
return skipBytes(1);
|
||||
|
||||
case 0xcd:
|
||||
if (allowValue)
|
||||
return readInteger<uint16_t>(variant);
|
||||
else
|
||||
return skipBytes(2);
|
||||
|
||||
case 0xce:
|
||||
if (allowValue)
|
||||
return readInteger<uint32_t>(variant);
|
||||
else
|
||||
return skipBytes(4);
|
||||
|
||||
case 0xcf:
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
if (allowValue)
|
||||
return readInteger<uint64_t>(variant);
|
||||
else
|
||||
return skipBytes(8);
|
||||
#else
|
||||
return skipBytes(8); // not supported
|
||||
#endif
|
||||
|
||||
case 0xd0:
|
||||
if (allowValue)
|
||||
return readInteger<int8_t>(variant);
|
||||
else
|
||||
return skipBytes(1);
|
||||
|
||||
case 0xd1:
|
||||
if (allowValue)
|
||||
return readInteger<int16_t>(variant);
|
||||
else
|
||||
return skipBytes(2);
|
||||
|
||||
case 0xd2:
|
||||
if (allowValue)
|
||||
return readInteger<int32_t>(variant);
|
||||
else
|
||||
return skipBytes(4);
|
||||
|
||||
case 0xd3:
|
||||
#if ARDUINOJSON_USE_LONG_LONG
|
||||
if (allowValue)
|
||||
return readInteger<int64_t>(variant);
|
||||
else
|
||||
return skipBytes(8);
|
||||
#else
|
||||
return skipBytes(8); // not supported
|
||||
#endif
|
||||
}
|
||||
|
||||
if (code <= 0x7f || code >= 0xe0) { // fixint
|
||||
@ -259,29 +211,38 @@ class MsgPackDeserializer {
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
DeserializationError::Code readInteger(T& value) {
|
||||
DeserializationError::Code err;
|
||||
DeserializationError::Code readInteger(VariantData* variant, uint8_t width,
|
||||
bool isSigned) {
|
||||
uint8_t buffer[8];
|
||||
|
||||
err = readBytes(value);
|
||||
auto err = readBytes(buffer, width);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
fixEndianness(value);
|
||||
union {
|
||||
int64_t signedValue;
|
||||
uint64_t unsignedValue;
|
||||
};
|
||||
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
if (isSigned)
|
||||
signedValue = static_cast<int8_t>(buffer[0]); // propagate sign bit
|
||||
else
|
||||
unsignedValue = static_cast<uint8_t>(buffer[0]);
|
||||
|
||||
template <typename T>
|
||||
DeserializationError::Code readInteger(VariantData* variant) {
|
||||
DeserializationError::Code err;
|
||||
T value;
|
||||
for (uint8_t i = 1; i < width; i++)
|
||||
unsignedValue = (unsignedValue << 8) | buffer[i];
|
||||
|
||||
err = readInteger(value);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
variant->setInteger(value);
|
||||
if (isSigned) {
|
||||
auto truncatedValue = static_cast<JsonInteger>(signedValue);
|
||||
if (truncatedValue == signedValue)
|
||||
variant->setInteger(truncatedValue);
|
||||
// else set null on overflow
|
||||
} else {
|
||||
auto truncatedValue = static_cast<JsonUInt>(unsignedValue);
|
||||
if (truncatedValue == unsignedValue)
|
||||
variant->setInteger(truncatedValue);
|
||||
// else set null on overflow
|
||||
}
|
||||
|
||||
return DeserializationError::Ok;
|
||||
}
|
||||
|
Reference in New Issue
Block a user