diff --git a/.gitignore b/.gitignore index 59b4e3e2..948f96c2 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ build/ .DS_store .idea/ cmake-build-*/ +tmpunwind.o diff --git a/Distribution/LuaBridge/LuaBridge.h b/Distribution/LuaBridge/LuaBridge.h index a773d348..315fbe1e 100644 --- a/Distribution/LuaBridge/LuaBridge.h +++ b/Distribution/LuaBridge/LuaBridge.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -689,8 +690,11 @@ bool is_integral_representable_by(lua_State* L, int index) } template -constexpr bool is_floating_point_representable_by(T value) +bool is_floating_point_representable_by(T value) { + if (std::isnan(value) || std::isinf(value)) + return true; + if constexpr (sizeof(T) == sizeof(U)) return true; diff --git a/Source/LuaBridge/detail/LuaHelpers.h b/Source/LuaBridge/detail/LuaHelpers.h index 62e83ffb..a8f6aae4 100644 --- a/Source/LuaBridge/detail/LuaHelpers.h +++ b/Source/LuaBridge/detail/LuaHelpers.h @@ -8,6 +8,7 @@ #include "Config.h" +#include #include #include #include @@ -626,26 +627,33 @@ constexpr bool is_integral_representable_by(T value) if constexpr (sizeof(T) == sizeof(U)) { if constexpr (same_signedness) + { return true; - - if constexpr (std::is_unsigned_v) + } + else if constexpr (std::is_unsigned_v) + { return value <= static_cast((std::numeric_limits::max)()); - - return value >= static_cast((std::numeric_limits::min)()) - && static_cast(value) <= (std::numeric_limits::max)(); + } + else + { + return value >= static_cast((std::numeric_limits::min)()) + && static_cast(value) <= (std::numeric_limits::max)(); + } } - - if constexpr (sizeof(T) < sizeof(U)) + else if constexpr (sizeof(T) < sizeof(U)) { return static_cast(value) >= (std::numeric_limits::min)() && static_cast(value) <= (std::numeric_limits::max)(); } - - if constexpr (std::is_unsigned_v) + else if constexpr (std::is_unsigned_v) + { return value <= static_cast((std::numeric_limits::max)()); - - return value >= static_cast((std::numeric_limits::min)()) - && value <= static_cast((std::numeric_limits::max)()); + } + else + { + return value >= static_cast((std::numeric_limits::min)()) + && value <= static_cast((std::numeric_limits::max)()); + } } template @@ -662,17 +670,28 @@ bool is_integral_representable_by(lua_State* L, int index) * @brief Checks if the value on the stack is a number type and can fit into the corresponding c++ numerical type.. */ template -constexpr bool is_floating_point_representable_by(T value) +bool is_floating_point_representable_by(T value) { if constexpr (sizeof(T) == sizeof(U)) + { return true; + } + else if constexpr (sizeof(T) < sizeof(U)) + { + if (std::isnan(value) || std::isinf(value)) + return true; - if constexpr (sizeof(T) < sizeof(U)) return static_cast(value) >= -(std::numeric_limits::max)() && static_cast(value) <= (std::numeric_limits::max)(); + } + else + { + if (std::isnan(value) || std::isinf(value)) + return true; - return value >= static_cast(-(std::numeric_limits::max)()) - && value <= static_cast((std::numeric_limits::max)()); + return value >= static_cast(-(std::numeric_limits::max)()) + && value <= static_cast((std::numeric_limits::max)()); + } } template diff --git a/Tests/Source/StackTests.cpp b/Tests/Source/StackTests.cpp index 4793c4a2..daedd22f 100644 --- a/Tests/Source/StackTests.cpp +++ b/Tests/Source/StackTests.cpp @@ -1404,6 +1404,108 @@ TEST_F(StackTests, FloatTypeNotFittingIsInstance) EXPECT_TRUE(luabridge::isInstance(L, 1)); } +TEST_F(StackTests, FloatNaNAndInfPush) +{ + { + const luabridge::StackRestore sr(L); + EXPECT_TRUE(luabridge::push(L, std::numeric_limits::quiet_NaN())); + EXPECT_TRUE(luabridge::isInstance(L, -1)); + EXPECT_TRUE(luabridge::isInstance(L, -1)); + EXPECT_TRUE(luabridge::isInstance(L, -1)); + auto result = luabridge::get(L, -1); + ASSERT_TRUE(result); + EXPECT_TRUE(std::isnan(*result)); + } + + { + const luabridge::StackRestore sr(L); + EXPECT_TRUE(luabridge::push(L, std::numeric_limits::infinity())); + EXPECT_TRUE(luabridge::isInstance(L, -1)); + EXPECT_TRUE(luabridge::isInstance(L, -1)); + EXPECT_TRUE(luabridge::isInstance(L, -1)); + auto result = luabridge::get(L, -1); + ASSERT_TRUE(result); + EXPECT_TRUE(std::isinf(*result)); + } + + { + const luabridge::StackRestore sr(L); + EXPECT_TRUE(luabridge::push(L, -std::numeric_limits::infinity())); + auto result = luabridge::get(L, -1); + ASSERT_TRUE(result); + EXPECT_TRUE(std::isinf(*result)); + EXPECT_LT(*result, 0.0f); + } +} + +TEST_F(StackTests, DoubleNaNAndInfPush) +{ + { + const luabridge::StackRestore sr(L); + EXPECT_TRUE(luabridge::push(L, std::numeric_limits::quiet_NaN())); + EXPECT_TRUE(luabridge::isInstance(L, -1)); + EXPECT_TRUE(luabridge::isInstance(L, -1)); + EXPECT_TRUE(luabridge::isInstance(L, -1)); + auto result = luabridge::get(L, -1); + ASSERT_TRUE(result); + EXPECT_TRUE(std::isnan(*result)); + } + + { + const luabridge::StackRestore sr(L); + EXPECT_TRUE(luabridge::push(L, std::numeric_limits::infinity())); + EXPECT_TRUE(luabridge::isInstance(L, -1)); + EXPECT_TRUE(luabridge::isInstance(L, -1)); + EXPECT_TRUE(luabridge::isInstance(L, -1)); + auto result = luabridge::get(L, -1); + ASSERT_TRUE(result); + EXPECT_TRUE(std::isinf(*result)); + } + + { + const luabridge::StackRestore sr(L); + EXPECT_TRUE(luabridge::push(L, -std::numeric_limits::infinity())); + auto result = luabridge::get(L, -1); + ASSERT_TRUE(result); + EXPECT_TRUE(std::isinf(*result)); + EXPECT_LT(*result, 0.0); + } +} + +TEST_F(StackTests, LongDoubleNaNAndInfPush) +{ + { + const luabridge::StackRestore sr(L); + EXPECT_TRUE(luabridge::push(L, std::numeric_limits::quiet_NaN())); + EXPECT_TRUE(luabridge::isInstance(L, -1)); + EXPECT_TRUE(luabridge::isInstance(L, -1)); + EXPECT_TRUE(luabridge::isInstance(L, -1)); + auto result = luabridge::get(L, -1); + ASSERT_TRUE(result); + EXPECT_TRUE(std::isnan(*result)); + } + + { + const luabridge::StackRestore sr(L); + EXPECT_TRUE(luabridge::push(L, std::numeric_limits::infinity())); + EXPECT_TRUE(luabridge::isInstance(L, -1)); + EXPECT_TRUE(luabridge::isInstance(L, -1)); + EXPECT_TRUE(luabridge::isInstance(L, -1)); + auto result = luabridge::get(L, -1); + ASSERT_TRUE(result); + EXPECT_TRUE(std::isinf(*result)); + } + + { + const luabridge::StackRestore sr(L); + EXPECT_TRUE(luabridge::push(L, -std::numeric_limits::infinity())); + auto result = luabridge::get(L, -1); + ASSERT_TRUE(result); + EXPECT_TRUE(std::isinf(*result)); + EXPECT_LT(*result, 0.0l); + } +} + TEST_F(StackTests, CharArrayType) { char value[] = "xyz";