Skip to content

Commit ea8061e

Browse files
authored
Allow NaN and Inf to pass through Stack floating-point push/get/isInstance (#208)
1 parent 08fc6de commit ea8061e

File tree

4 files changed

+143
-17
lines changed

4 files changed

+143
-17
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ build/
1414
.DS_store
1515
.idea/
1616
cmake-build-*/
17+
tmpunwind.o

Distribution/LuaBridge/LuaBridge.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <algorithm>
1010
#include <array>
1111
#include <cassert>
12+
#include <cmath>
1213
#include <cstddef>
1314
#include <cstdint>
1415
#include <cstdio>
@@ -689,8 +690,11 @@ bool is_integral_representable_by(lua_State* L, int index)
689690
}
690691

691692
template <class U = lua_Number, class T>
692-
constexpr bool is_floating_point_representable_by(T value)
693+
bool is_floating_point_representable_by(T value)
693694
{
695+
if (std::isnan(value) || std::isinf(value))
696+
return true;
697+
694698
if constexpr (sizeof(T) == sizeof(U))
695699
return true;
696700

Source/LuaBridge/detail/LuaHelpers.h

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "Config.h"
1010

11+
#include <cmath>
1112
#include <cstdint>
1213
#include <cstdio>
1314
#include <cstdlib>
@@ -626,26 +627,33 @@ constexpr bool is_integral_representable_by(T value)
626627
if constexpr (sizeof(T) == sizeof(U))
627628
{
628629
if constexpr (same_signedness)
630+
{
629631
return true;
630-
631-
if constexpr (std::is_unsigned_v<T>)
632+
}
633+
else if constexpr (std::is_unsigned_v<T>)
634+
{
632635
return value <= static_cast<T>((std::numeric_limits<U>::max)());
633-
634-
return value >= static_cast<T>((std::numeric_limits<U>::min)())
635-
&& static_cast<U>(value) <= (std::numeric_limits<U>::max)();
636+
}
637+
else
638+
{
639+
return value >= static_cast<T>((std::numeric_limits<U>::min)())
640+
&& static_cast<U>(value) <= (std::numeric_limits<U>::max)();
641+
}
636642
}
637-
638-
if constexpr (sizeof(T) < sizeof(U))
643+
else if constexpr (sizeof(T) < sizeof(U))
639644
{
640645
return static_cast<U>(value) >= (std::numeric_limits<U>::min)()
641646
&& static_cast<U>(value) <= (std::numeric_limits<U>::max)();
642647
}
643-
644-
if constexpr (std::is_unsigned_v<T>)
648+
else if constexpr (std::is_unsigned_v<T>)
649+
{
645650
return value <= static_cast<T>((std::numeric_limits<U>::max)());
646-
647-
return value >= static_cast<T>((std::numeric_limits<U>::min)())
648-
&& value <= static_cast<T>((std::numeric_limits<U>::max)());
651+
}
652+
else
653+
{
654+
return value >= static_cast<T>((std::numeric_limits<U>::min)())
655+
&& value <= static_cast<T>((std::numeric_limits<U>::max)());
656+
}
649657
}
650658

651659
template <class U = lua_Integer>
@@ -662,17 +670,28 @@ bool is_integral_representable_by(lua_State* L, int index)
662670
* @brief Checks if the value on the stack is a number type and can fit into the corresponding c++ numerical type..
663671
*/
664672
template <class U = lua_Number, class T>
665-
constexpr bool is_floating_point_representable_by(T value)
673+
bool is_floating_point_representable_by(T value)
666674
{
667675
if constexpr (sizeof(T) == sizeof(U))
676+
{
668677
return true;
678+
}
679+
else if constexpr (sizeof(T) < sizeof(U))
680+
{
681+
if (std::isnan(value) || std::isinf(value))
682+
return true;
669683

670-
if constexpr (sizeof(T) < sizeof(U))
671684
return static_cast<U>(value) >= -(std::numeric_limits<U>::max)()
672685
&& static_cast<U>(value) <= (std::numeric_limits<U>::max)();
686+
}
687+
else
688+
{
689+
if (std::isnan(value) || std::isinf(value))
690+
return true;
673691

674-
return value >= static_cast<T>(-(std::numeric_limits<U>::max)())
675-
&& value <= static_cast<T>((std::numeric_limits<U>::max)());
692+
return value >= static_cast<T>(-(std::numeric_limits<U>::max)())
693+
&& value <= static_cast<T>((std::numeric_limits<U>::max)());
694+
}
676695
}
677696

678697
template <class U = lua_Number>

Tests/Source/StackTests.cpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,6 +1404,108 @@ TEST_F(StackTests, FloatTypeNotFittingIsInstance)
14041404
EXPECT_TRUE(luabridge::isInstance<long double>(L, 1));
14051405
}
14061406

1407+
TEST_F(StackTests, FloatNaNAndInfPush)
1408+
{
1409+
{
1410+
const luabridge::StackRestore sr(L);
1411+
EXPECT_TRUE(luabridge::push(L, std::numeric_limits<float>::quiet_NaN()));
1412+
EXPECT_TRUE(luabridge::isInstance<float>(L, -1));
1413+
EXPECT_TRUE(luabridge::isInstance<double>(L, -1));
1414+
EXPECT_TRUE(luabridge::isInstance<long double>(L, -1));
1415+
auto result = luabridge::get<float>(L, -1);
1416+
ASSERT_TRUE(result);
1417+
EXPECT_TRUE(std::isnan(*result));
1418+
}
1419+
1420+
{
1421+
const luabridge::StackRestore sr(L);
1422+
EXPECT_TRUE(luabridge::push(L, std::numeric_limits<float>::infinity()));
1423+
EXPECT_TRUE(luabridge::isInstance<float>(L, -1));
1424+
EXPECT_TRUE(luabridge::isInstance<double>(L, -1));
1425+
EXPECT_TRUE(luabridge::isInstance<long double>(L, -1));
1426+
auto result = luabridge::get<float>(L, -1);
1427+
ASSERT_TRUE(result);
1428+
EXPECT_TRUE(std::isinf(*result));
1429+
}
1430+
1431+
{
1432+
const luabridge::StackRestore sr(L);
1433+
EXPECT_TRUE(luabridge::push(L, -std::numeric_limits<float>::infinity()));
1434+
auto result = luabridge::get<float>(L, -1);
1435+
ASSERT_TRUE(result);
1436+
EXPECT_TRUE(std::isinf(*result));
1437+
EXPECT_LT(*result, 0.0f);
1438+
}
1439+
}
1440+
1441+
TEST_F(StackTests, DoubleNaNAndInfPush)
1442+
{
1443+
{
1444+
const luabridge::StackRestore sr(L);
1445+
EXPECT_TRUE(luabridge::push(L, std::numeric_limits<double>::quiet_NaN()));
1446+
EXPECT_TRUE(luabridge::isInstance<float>(L, -1));
1447+
EXPECT_TRUE(luabridge::isInstance<double>(L, -1));
1448+
EXPECT_TRUE(luabridge::isInstance<long double>(L, -1));
1449+
auto result = luabridge::get<double>(L, -1);
1450+
ASSERT_TRUE(result);
1451+
EXPECT_TRUE(std::isnan(*result));
1452+
}
1453+
1454+
{
1455+
const luabridge::StackRestore sr(L);
1456+
EXPECT_TRUE(luabridge::push(L, std::numeric_limits<double>::infinity()));
1457+
EXPECT_TRUE(luabridge::isInstance<float>(L, -1));
1458+
EXPECT_TRUE(luabridge::isInstance<double>(L, -1));
1459+
EXPECT_TRUE(luabridge::isInstance<long double>(L, -1));
1460+
auto result = luabridge::get<double>(L, -1);
1461+
ASSERT_TRUE(result);
1462+
EXPECT_TRUE(std::isinf(*result));
1463+
}
1464+
1465+
{
1466+
const luabridge::StackRestore sr(L);
1467+
EXPECT_TRUE(luabridge::push(L, -std::numeric_limits<double>::infinity()));
1468+
auto result = luabridge::get<double>(L, -1);
1469+
ASSERT_TRUE(result);
1470+
EXPECT_TRUE(std::isinf(*result));
1471+
EXPECT_LT(*result, 0.0);
1472+
}
1473+
}
1474+
1475+
TEST_F(StackTests, LongDoubleNaNAndInfPush)
1476+
{
1477+
{
1478+
const luabridge::StackRestore sr(L);
1479+
EXPECT_TRUE(luabridge::push(L, std::numeric_limits<long double>::quiet_NaN()));
1480+
EXPECT_TRUE(luabridge::isInstance<float>(L, -1));
1481+
EXPECT_TRUE(luabridge::isInstance<double>(L, -1));
1482+
EXPECT_TRUE(luabridge::isInstance<long double>(L, -1));
1483+
auto result = luabridge::get<long double>(L, -1);
1484+
ASSERT_TRUE(result);
1485+
EXPECT_TRUE(std::isnan(*result));
1486+
}
1487+
1488+
{
1489+
const luabridge::StackRestore sr(L);
1490+
EXPECT_TRUE(luabridge::push(L, std::numeric_limits<long double>::infinity()));
1491+
EXPECT_TRUE(luabridge::isInstance<float>(L, -1));
1492+
EXPECT_TRUE(luabridge::isInstance<double>(L, -1));
1493+
EXPECT_TRUE(luabridge::isInstance<long double>(L, -1));
1494+
auto result = luabridge::get<long double>(L, -1);
1495+
ASSERT_TRUE(result);
1496+
EXPECT_TRUE(std::isinf(*result));
1497+
}
1498+
1499+
{
1500+
const luabridge::StackRestore sr(L);
1501+
EXPECT_TRUE(luabridge::push(L, -std::numeric_limits<long double>::infinity()));
1502+
auto result = luabridge::get<long double>(L, -1);
1503+
ASSERT_TRUE(result);
1504+
EXPECT_TRUE(std::isinf(*result));
1505+
EXPECT_LT(*result, 0.0l);
1506+
}
1507+
}
1508+
14071509
TEST_F(StackTests, CharArrayType)
14081510
{
14091511
char value[] = "xyz";

0 commit comments

Comments
 (0)