Break build if using 64-bit integers with ARDUINOJSON_USE_LONG_LONG==0

This commit is contained in:
Benoit Blanchon
2020-05-12 18:53:26 +02:00
parent bc4c2dde33
commit f7de027617
10 changed files with 75 additions and 44 deletions

View File

@ -11,6 +11,7 @@ HEAD
* Added support for `enum`s in `as<T>()` and `is<T>()` (issue #1256) * Added support for `enum`s in `as<T>()` and `is<T>()` (issue #1256)
* Added `JsonVariant` as an input type for `deserializeXxx()` * Added `JsonVariant` as an input type for `deserializeXxx()`
For example, you can do: `deserializeJson(doc2, doc1["payload"])` For example, you can do: `deserializeJson(doc2, doc1["payload"])`
* Break the build if using 64-bit integers with ARDUINOJSON_USE_LONG_LONG==0
v6.15.1 (2020-04-08) v6.15.1 (2020-04-08)
------- -------

View File

@ -28,3 +28,11 @@ build_should_fail(Issue978)
add_executable(Issue1189 Issue1189.cpp) add_executable(Issue1189 Issue1189.cpp)
build_should_fail(Issue1189) build_should_fail(Issue1189)
add_executable(read_long_long read_long_long.cpp)
set_property(TARGET read_long_long PROPERTY CXX_STANDARD 11)
build_should_fail(read_long_long)
add_executable(write_long_long write_long_long.cpp)
set_property(TARGET write_long_long PROPERTY CXX_STANDARD 11)
build_should_fail(write_long_long)

View File

@ -0,0 +1,20 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020
// MIT License
#define ARDUINOJSON_USE_LONG_LONG 0
#include <ArduinoJson.h>
#if defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ >= 8
#error This test requires sizeof(long) < 8
#endif
#if !ARDUINOJSON_HAS_LONG_LONG
#error This test requires C++11
#endif
ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(long long)
int main() {
DynamicJsonDocument doc(1024);
doc["dummy"].as<long long>();
}

View File

@ -0,0 +1,19 @@
// ArduinoJson - arduinojson.org
// Copyright Benoit Blanchon 2014-2020
// MIT License
#define ARDUINOJSON_USE_LONG_LONG 0
#include <ArduinoJson.h>
#if defined(__SIZEOF_LONG__) && __SIZEOF_LONG__ >= 8
#error This test requires sizeof(long) < 8
#endif
#if !ARDUINOJSON_HAS_LONG_LONG
#error This test requires C++11
#endif
int main() {
DynamicJsonDocument doc(1024);
doc["dummy"] = static_cast<long long>(42);
}

View File

@ -3,28 +3,14 @@
#include <catch.hpp> #include <catch.hpp>
template <size_t size_of_long>
std::string get_expected_json();
template <>
std::string get_expected_json<4>() {
return "{\"A\":2899336981,\"B\":2129924785}";
}
template <>
std::string get_expected_json<8>() {
return "{\"A\":123456789123456789,\"B\":987654321987654321}";
}
TEST_CASE("ARDUINOJSON_USE_LONG_LONG == 0") { TEST_CASE("ARDUINOJSON_USE_LONG_LONG == 0") {
DynamicJsonDocument doc(4096); DynamicJsonDocument doc(4096);
JsonObject root = doc.to<JsonObject>();
root["A"] = 123456789123456789; doc["A"] = 42;
root["B"] = 987654321987654321; doc["B"] = 84;
std::string json; std::string json;
serializeJson(doc, json); serializeJson(doc, json);
REQUIRE(json == get_expected_json<sizeof(long)>()); REQUIRE(json == "{\"A\":42,\"B\":84}");
} }

View File

@ -18,4 +18,15 @@ typedef uint64_t UInt;
typedef long Integer; typedef long Integer;
typedef unsigned long UInt; typedef unsigned long UInt;
#endif #endif
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE
#if ARDUINOJSON_HAS_LONG_LONG && !ARDUINOJSON_USE_LONG_LONG
#define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T) \
static_assert(sizeof(T) <= sizeof(ARDUINOJSON_NAMESPACE::Integer), \
"To use 64-bit integers with ArduinoJson, you must set " \
"ARDUINOJSON_USE_LONG_LONG to 1. See " \
"https://arduinojson.org/v6/api/config/use_long_long/");
#else
#define ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T)
#endif

View File

@ -55,6 +55,7 @@ struct VariantConstAs<ArrayRef> {
template <typename T> template <typename T>
inline typename enable_if<is_integral<T>::value, T>::type variantAs( inline typename enable_if<is_integral<T>::value, T>::type variantAs(
const VariantData* data) { const VariantData* data) {
ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
return data != 0 ? data->asIntegral<T>() : T(0); return data != 0 ? data->asIntegral<T>() : T(0);
} }

View File

@ -258,6 +258,11 @@ class VariantData {
} }
} }
void setUnsignedInteger(UInt value) {
setType(VALUE_IS_POSITIVE_INTEGER);
_content.asInteger = static_cast<UInt>(value);
}
void setPositiveInteger(UInt value) { void setPositiveInteger(UInt value) {
setType(VALUE_IS_POSITIVE_INTEGER); setType(VALUE_IS_POSITIVE_INTEGER);
_content.asInteger = value; _content.asInteger = value;
@ -301,11 +306,6 @@ class VariantData {
return setOwnedString(value.save(pool)); return setOwnedString(value.save(pool));
} }
void setUnsignedInteger(UInt value) {
setType(VALUE_IS_POSITIVE_INTEGER);
_content.asInteger = static_cast<UInt>(value);
}
CollectionData &toArray() { CollectionData &toArray() {
setType(VALUE_IS_ARRAY); setType(VALUE_IS_ARRAY);
_content.asCollection.clear(); _content.asCollection.clear();

View File

@ -105,14 +105,6 @@ inline bool variantSetOwnedRaw(VariantData *var, SerializedValue<T> value,
return var != 0 && var->setOwnedRaw(value, pool); return var != 0 && var->setOwnedRaw(value, pool);
} }
template <typename T>
inline bool variantSetSignedInteger(VariantData *var, T value) {
if (!var)
return false;
var->setSignedInteger(value);
return true;
}
inline bool variantSetLinkedString(VariantData *var, const char *value) { inline bool variantSetLinkedString(VariantData *var, const char *value) {
if (!var) if (!var)
return false; return false;
@ -138,10 +130,12 @@ inline bool variantSetOwnedString(VariantData *var, T value, MemoryPool *pool) {
return var != 0 && var->setOwnedString(value, pool); return var != 0 && var->setOwnedString(value, pool);
} }
inline bool variantSetUnsignedInteger(VariantData *var, UInt value) { template <typename T>
inline bool variantSetInteger(VariantData *var, T value) {
ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
if (!var) if (!var)
return false; return false;
var->setUnsignedInteger(value); var->setInteger(value);
return true; return true;
} }

View File

@ -178,22 +178,13 @@ class VariantRef : public VariantRefBase<VariantData>,
// set(signed int) // set(signed int)
// set(signed long) // set(signed long)
// set(signed char) // set(signed char)
template <typename T>
FORCE_INLINE bool set(
T value,
typename enable_if<is_integral<T>::value && is_signed<T>::value>::type * =
0) const {
return variantSetSignedInteger(_data, value);
}
// set(unsigned short) // set(unsigned short)
// set(unsigned int) // set(unsigned int)
// set(unsigned long) // set(unsigned long)
template <typename T> template <typename T>
FORCE_INLINE bool set( FORCE_INLINE bool set(
T value, typename enable_if<is_integral<T>::value && T value, typename enable_if<is_integral<T>::value>::type * = 0) const {
is_unsigned<T>::value>::type * = 0) const { return variantSetInteger<T>(_data, value);
return variantSetUnsignedInteger(_data, static_cast<UInt>(value));
} }
// set(SerializedValue<const char *>) // set(SerializedValue<const char *>)
@ -248,7 +239,7 @@ class VariantRef : public VariantRefBase<VariantData>,
template <typename T> template <typename T>
FORCE_INLINE bool set( FORCE_INLINE bool set(
T value, typename enable_if<is_enum<T>::value>::type * = 0) const { T value, typename enable_if<is_enum<T>::value>::type * = 0) const {
return variantSetSignedInteger(_data, static_cast<Integer>(value)); return variantSetInteger(_data, static_cast<Integer>(value));
} }
template <typename T> template <typename T>