From 428dddf2cc7997caf5b72fcf087eaae9794bf433 Mon Sep 17 00:00:00 2001 From: Benoit Blanchon Date: Sat, 6 Feb 2016 21:21:34 +0100 Subject: [PATCH] Fix build on Visual Studio 2010, 2012, MinGW32 and GCC 5 --- appveyor.yml | 16 +++++ include/ArduinoJson/Arduino/Print.hpp | 48 +++++++++++---- include/ArduinoJson/JsonArraySubscript.hpp | 5 -- include/ArduinoJson/JsonObjectSubscript.hpp | 4 -- include/ArduinoJson/JsonVariant.hpp | 31 ++++++---- include/ArduinoJson/TypeTraits/IsIntegral.hpp | 13 ++-- src/Arduino/Print.cpp | 60 ------------------- test/JsonArray_Subscript_Tests.cpp | 8 ++- test/JsonVariant_As_Tests.cpp | 8 ++- test/JsonVariant_PrintTo_Tests.cpp | 2 + test/JsonVariant_Storage_Tests.cpp | 16 +++-- 11 files changed, 106 insertions(+), 105 deletions(-) create mode 100644 appveyor.yml delete mode 100644 src/Arduino/Print.cpp diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..60db62b9 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,16 @@ +version: 5.1.0.{build} +environment: + matrix: + - CMAKE_GENERATOR: Visual Studio 14 2015 + - CMAKE_GENERATOR: Visual Studio 12 2013 + - CMAKE_GENERATOR: Visual Studio 11 2012 + - CMAKE_GENERATOR: Visual Studio 10 2010 + - CMAKE_GENERATOR: MinGW Makefiles +configuration: Debug +before_build: +- set PATH=C:\MinGW\bin;%PATH:C:\Program Files\Git\usr\bin;=% # Workaround for CMake not wanting sh.exe on PATH for MinGW +- cmake -DCMAKE_BUILD_TYPE=%CONFIGURATION% -G "%CMAKE_GENERATOR%" . +build_script: +- cmake --build . --config %CONFIGURATION% +test_script: +- ctest -V . diff --git a/include/ArduinoJson/Arduino/Print.hpp b/include/ArduinoJson/Arduino/Print.hpp index 139a3ad7..3ec2e90a 100644 --- a/include/ArduinoJson/Arduino/Print.hpp +++ b/include/ArduinoJson/Arduino/Print.hpp @@ -9,11 +9,19 @@ #ifndef ARDUINO -#include "../TypeTraits/EnableIf.hpp" -#include "../TypeTraits/IsIntegral.hpp" +#include "../Internals/JsonFloat.hpp" +#include "../Internals/JsonInteger.hpp" #include #include +#include + +#if defined(_MSC_VER) && _MSC_VER <= 1800 +// snprintf has been added in Visual Studio 2015 +#define ARDUINOJSON_SNPRINTF _snprintf +#else +#define ARDUINOJSON_SNPRINTF snprintf +#endif // This class reproduces Arduino's Print class class Print { @@ -22,13 +30,33 @@ class Print { virtual size_t write(uint8_t) = 0; - size_t print(const char[]); - size_t print(double, int = 2); + size_t print(const char* s) { + size_t n = 0; + while (*s) { + n += write(*s++); + } + return n; + } - template - typename ArduinoJson::TypeTraits::EnableIf< - ArduinoJson::TypeTraits::IsIntegral::value, size_t>::type - print(TIntegral value) { + size_t print(ArduinoJson::Internals::JsonFloat value, int digits = 2) { + char tmp[32]; + + // https://github.com/arduino/Arduino/blob/db8cbf24c99dc930b9ccff1a43d018c81f178535/hardware/arduino/sam/cores/arduino/Print.cpp#L220 + bool isBigDouble = value > 4294967040.0 || value < -4294967040.0; + + if (isBigDouble) { + // Arduino's implementation prints "ovf" + // We prefer using the scientific notation, since we have sprintf + ARDUINOJSON_SNPRINTF(tmp, sizeof(tmp), "%g", value); + } else { + // Here we have the exact same output as Arduino's implementation + ARDUINOJSON_SNPRINTF(tmp, sizeof(tmp), "%.*f", digits, value); + } + + return print(tmp); + } + + size_t print(ArduinoJson::Internals::JsonInteger value) { // see http://clc-wiki.net/wiki/K%26R2_solutions:Chapter_3:Exercise_4 char buffer[22]; @@ -39,7 +67,7 @@ class Print { } uint8_t i = 0; do { - TIntegral digit = value % 10; + ArduinoJson::Internals::JsonInteger digit = value % 10; value /= 10; buffer[i++] = static_cast(digit >= 0 ? '0' + digit : '0' - digit); } while (value); @@ -51,7 +79,7 @@ class Print { return n; } - size_t println(); + size_t println() { return write('\r') + write('\n'); } }; #else diff --git a/include/ArduinoJson/JsonArraySubscript.hpp b/include/ArduinoJson/JsonArraySubscript.hpp index 47ed425e..8c489680 100644 --- a/include/ArduinoJson/JsonArraySubscript.hpp +++ b/include/ArduinoJson/JsonArraySubscript.hpp @@ -77,11 +77,6 @@ inline std::ostream& operator<<(std::ostream& os, } #endif -template <> -struct JsonVariant::IsConstructibleFrom { - static const bool value = true; -}; - } // namespace ArduinoJson #ifdef _MSC_VER diff --git a/include/ArduinoJson/JsonObjectSubscript.hpp b/include/ArduinoJson/JsonObjectSubscript.hpp index 2b26cc9b..3916a917 100644 --- a/include/ArduinoJson/JsonObjectSubscript.hpp +++ b/include/ArduinoJson/JsonObjectSubscript.hpp @@ -92,10 +92,6 @@ inline std::ostream& operator<<( } #endif -template -struct JsonVariant::IsConstructibleFrom > { - static const bool value = true; -}; } // namespace ArduinoJson #ifdef _MSC_VER diff --git a/include/ArduinoJson/JsonVariant.hpp b/include/ArduinoJson/JsonVariant.hpp index 4959ff77..98b4dc2d 100644 --- a/include/ArduinoJson/JsonVariant.hpp +++ b/include/ArduinoJson/JsonVariant.hpp @@ -18,9 +18,9 @@ #include "TypeTraits/EnableIf.hpp" #include "TypeTraits/IsFloatingPoint.hpp" #include "TypeTraits/IsIntegral.hpp" +#include "TypeTraits/IsSame.hpp" #include "TypeTraits/RemoveConst.hpp" #include "TypeTraits/RemoveReference.hpp" -#include "TypeTraits/IsSame.hpp" namespace ArduinoJson { @@ -191,17 +191,24 @@ inline JsonVariant double_with_n_digits(double value, uint8_t digits) { template struct JsonVariant::IsConstructibleFrom { - static const bool value = TypeTraits::IsIntegral::value || - TypeTraits::IsFloatingPoint::value || - TypeTraits::IsSame::value || - TypeTraits::IsSame::value || - TypeTraits::IsSame::value || - TypeTraits::IsSame::value || - TypeTraits::IsSame::value || - TypeTraits::IsSame::value || - TypeTraits::IsSame::value || - TypeTraits::IsSame::value || - TypeTraits::IsSame::value; + static const bool value = + TypeTraits::IsIntegral::value || + TypeTraits::IsFloatingPoint::value || + TypeTraits::IsSame::value || + TypeTraits::IsSame::value || + TypeTraits::IsSame::value || + TypeTraits::IsSame::value || + TypeTraits::IsSame::value || + TypeTraits::IsSame::value || + TypeTraits::IsSame::value || + TypeTraits::IsSame::value || + TypeTraits::IsSame::value || + TypeTraits::IsSame &>::value || + TypeTraits::IsSame &>::value || + TypeTraits::IsSame &>::value || + TypeTraits::IsSame &>::value || + TypeTraits::IsSame::value || + TypeTraits::IsSame::value; }; } diff --git a/include/ArduinoJson/TypeTraits/IsIntegral.hpp b/include/ArduinoJson/TypeTraits/IsIntegral.hpp index dff5c593..53183d5c 100644 --- a/include/ArduinoJson/TypeTraits/IsIntegral.hpp +++ b/include/ArduinoJson/TypeTraits/IsIntegral.hpp @@ -7,6 +7,7 @@ #pragma once +#include "../Configuration.hpp" #include "IsSame.hpp" #include @@ -25,10 +26,14 @@ struct IsIntegral { TypeTraits::IsSame::value || TypeTraits::IsSame::value || TypeTraits::IsSame::value || -#ifndef ARDUINO - // on a computer add support for 64 bit - TypeTraits::IsSame::value || - TypeTraits::IsSame::value || +#if ARDUINOJSON_USE_LONG_LONG + TypeTraits::IsSame::value || + TypeTraits::IsSame::value || +#endif + +#if ARDUINOJSON_USE_INT64 + TypeTraits::IsSame::value || + TypeTraits::IsSame::value || #endif TypeTraits::IsSame::value; }; diff --git a/src/Arduino/Print.cpp b/src/Arduino/Print.cpp deleted file mode 100644 index d53b7af2..00000000 --- a/src/Arduino/Print.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright Benoit Blanchon 2014-2016 -// MIT License -// -// Arduino JSON library -// https://github.com/bblanchon/ArduinoJson -// If you like this project, please add a star! - -#ifndef ARDUINO - -#include "../../include/ArduinoJson/Arduino/Print.hpp" - -#include -#include // for isnan() and isinf() - -// only for GCC 4.9+ -#if defined(__GNUC__) && \ - (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) -#pragma GCC diagnostic ignored "-Wfloat-conversion" -#endif - -// Visual Studo 2012 didn't have isnan, nor isinf -#if defined(_MSC_VER) && _MSC_VER <= 1700 -#include -#define isnan(x) _isnan(x) -#define isinf(x) (!_finite(x)) -#endif - -size_t Print::print(const char s[]) { - size_t n = 0; - while (*s) { - n += write(*s++); - } - return n; -} - -size_t Print::print(double value, int digits) { - // https://github.com/arduino/Arduino/blob/db8cbf24c99dc930b9ccff1a43d018c81f178535/hardware/arduino/sam/cores/arduino/Print.cpp#L218 - if (isnan(value)) return print("nan"); - if (isinf(value)) return print("inf"); - - char tmp[32]; - - // https://github.com/arduino/Arduino/blob/db8cbf24c99dc930b9ccff1a43d018c81f178535/hardware/arduino/sam/cores/arduino/Print.cpp#L220 - bool isBigDouble = value > 4294967040.0 || value < -4294967040.0; - - if (isBigDouble) { - // Arduino's implementation prints "ovf" - // We prefer trying to use scientific notation, since we have sprintf - sprintf(tmp, "%g", value); - } else { - // Here we have the exact same output as Arduino's implementation - sprintf(tmp, "%.*f", digits, value); - } - - return print(tmp); -} - -size_t Print::println() { return write('\r') + write('\n'); } - -#endif diff --git a/test/JsonArray_Subscript_Tests.cpp b/test/JsonArray_Subscript_Tests.cpp index c1710c55..e2da2c2d 100644 --- a/test/JsonArray_Subscript_Tests.cpp +++ b/test/JsonArray_Subscript_Tests.cpp @@ -5,8 +5,8 @@ // https://github.com/bblanchon/ArduinoJson // If you like this project, please add a star! -#include #include +#include #include class JsonArray_Subscript_Tests : public ::testing::Test { @@ -33,12 +33,14 @@ TEST_(StoreInteger) { EXPECT_FALSE(_array[0].is()); } -TEST_(StoreInt64) { +#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 +TEST_(StoreLongLong) { _array[0] = 9223372036854775807; - EXPECT_EQ(9223372036854775807, _array[0].as()); + EXPECT_EQ(9223372036854775807, _array[0].as()); EXPECT_TRUE(_array[0].is()); EXPECT_FALSE(_array[0].is()); } +#endif TEST_(StoreDouble) { _array[0] = 123.45; diff --git a/test/JsonVariant_As_Tests.cpp b/test/JsonVariant_As_Tests.cpp index 2d4c99fd..cc980ba3 100644 --- a/test/JsonVariant_As_Tests.cpp +++ b/test/JsonVariant_As_Tests.cpp @@ -5,9 +5,9 @@ // https://github.com/bblanchon/ArduinoJson // If you like this project, please add a star! -#include #include +#include #include static const char* null = 0; @@ -137,15 +137,17 @@ TEST(JsonVariant_As_Tests, NumberStringAsLong) { ASSERT_EQ(42L, variant.as()); } +#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 TEST(JsonVariant_As_Tests, NumberStringAsInt64Negative) { JsonVariant variant = "-9223372036854775808"; - ASSERT_EQ(-9223372036854775807 - 1, variant.as()); + ASSERT_EQ(-9223372036854775807 - 1, variant.as()); } TEST(JsonVariant_As_Tests, NumberStringAsInt64Positive) { JsonVariant variant = "9223372036854775807"; - ASSERT_EQ(9223372036854775807, variant.as()); + ASSERT_EQ(9223372036854775807, variant.as()); } +#endif TEST(JsonVariant_As_Tests, RandomStringAsBool) { JsonVariant variant = "hello"; diff --git a/test/JsonVariant_PrintTo_Tests.cpp b/test/JsonVariant_PrintTo_Tests.cpp index 084d7b89..ed031159 100644 --- a/test/JsonVariant_PrintTo_Tests.cpp +++ b/test/JsonVariant_PrintTo_Tests.cpp @@ -72,6 +72,7 @@ TEST_F(JsonVariant_PrintTo_Tests, OneFalse) { outputMustBe("false"); } +#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 TEST_F(JsonVariant_PrintTo_Tests, NegativeInt64) { variant = -9223372036854775807 - 1; outputMustBe("-9223372036854775808"); @@ -81,3 +82,4 @@ TEST_F(JsonVariant_PrintTo_Tests, PositiveInt64) { variant = 9223372036854775807; outputMustBe("9223372036854775807"); } +#endif diff --git a/test/JsonVariant_Storage_Tests.cpp b/test/JsonVariant_Storage_Tests.cpp index d5c57431..672ddd94 100644 --- a/test/JsonVariant_Storage_Tests.cpp +++ b/test/JsonVariant_Storage_Tests.cpp @@ -5,9 +5,9 @@ // https://github.com/bblanchon/ArduinoJson // If you like this project, please add a star! +#include #include #include -#include #include class JsonVariant_Storage_Tests : public ::testing::Test { @@ -37,9 +37,11 @@ class JsonVariant_Storage_Tests : public ::testing::Test { } }; +#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 TEST_F(JsonVariant_Storage_Tests, SizeOfJsonInteger) { ASSERT_EQ(8, sizeof(Internals::JsonInteger)); } +#endif TEST_F(JsonVariant_Storage_Tests, Null) { testValue(NULL); } TEST_F(JsonVariant_Storage_Tests, String) { testValue("hello"); } @@ -57,15 +59,21 @@ TEST_F(JsonVariant_Storage_Tests, UChar) { testNumericType(); } TEST_F(JsonVariant_Storage_Tests, UInt) { testNumericType(); } TEST_F(JsonVariant_Storage_Tests, ULong) { testNumericType(); } TEST_F(JsonVariant_Storage_Tests, UShort) { testNumericType(); } +#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 +TEST_F(JsonVariant_Storage_Tests, LongLong) { testNumericType(); } +TEST_F(JsonVariant_Storage_Tests, ULongLong) { testNumericType(); } +#endif TEST_F(JsonVariant_Storage_Tests, Int8) { testNumericType(); } -TEST_F(JsonVariant_Storage_Tests, Int16) { testNumericType(); } -TEST_F(JsonVariant_Storage_Tests, Int32) { testNumericType(); } -TEST_F(JsonVariant_Storage_Tests, Int64) { testNumericType(); } TEST_F(JsonVariant_Storage_Tests, Uint8) { testNumericType(); } +TEST_F(JsonVariant_Storage_Tests, Int16) { testNumericType(); } TEST_F(JsonVariant_Storage_Tests, Uint16) { testNumericType(); } +TEST_F(JsonVariant_Storage_Tests, Int32) { testNumericType(); } TEST_F(JsonVariant_Storage_Tests, Uint32) { testNumericType(); } +#if ARDUINOJSON_USE_LONG_LONG || ARDUINOJSON_USE_INT64 +TEST_F(JsonVariant_Storage_Tests, Int64) { testNumericType(); } TEST_F(JsonVariant_Storage_Tests, Uint64) { testNumericType(); } +#endif TEST_F(JsonVariant_Storage_Tests, CanStoreObject) { DynamicJsonBuffer jsonBuffer;