large integer

This commit is contained in:
mrgreywater 2017-08-11 14:59:43 +02:00 committed by The Phantom Derpstorm
parent 5e109c2c37
commit 372db6f6ab
8 changed files with 276 additions and 65 deletions

View File

@ -74,6 +74,29 @@ matrix:
- ninja-build - ninja-build
- libluajit-5.1-dev - libluajit-5.1-dev
# gcc-5:i386
- os: linux
env: COMPILER=g++-5 LUA_VERSION=luajit51:i386
compiler: gcc
install:
- sudo dpkg --add-architecture i386
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-5
- g++-5
- ninja-build
- libluajit-5.1-dev
- libluajit-5.1-dev:i386
- libc6:i386
- libncurses5:i386
- libstdc++6:i386
- gcc-5-multilib
- g++-5-multilib
- linux-libc-dev:i386
# clang # clang
- os: linux - os: linux
env: env:

View File

@ -91,6 +91,12 @@ if 'linux' in sys.platform:
# Using normal lua # Using normal lua
lua_lib = lua_version[:-1] + '.' + lua_version[-1] lua_lib = lua_version[:-1] + '.' + lua_version[-1]
lua_incl = lua_lib lua_incl = lua_lib
elif re.match(r'luajit5[1-3]:i386', lua_version):
# luajit:i386
lua_incl = 'luajit-2.0'
lua_lib = lua_version[:-7] + '-' + lua_version[-7] + '.' + lua_version[-6]
cxxflags.append('-m32')
include.extend(['/usr/include/luajit-2.0/', '/usr/local/include/luajit-2.0/'])
elif re.match(r'luajit5[1-3]', lua_version): elif re.match(r'luajit5[1-3]', lua_version):
# luajit # luajit
lua_incl = 'luajit-2.0' # I don't get this.. lua_incl = 'luajit-2.0' # I don't get this..

View File

@ -20,8 +20,8 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This file was generated with a script. // This file was generated with a script.
// Generated 2017-08-11 14:35:51.568053 UTC // Generated 2017-08-11 12:59:23.551177 UTC
// This header was generated with sol v2.18.0 (revision 4f7f1af) // This header was generated with sol v2.18.0 (revision 5e109c2)
// https://github.com/ThePhD/sol2 // https://github.com/ThePhD/sol2
#ifndef SOL_SINGLE_INCLUDE_HPP #ifndef SOL_SINGLE_INCLUDE_HPP
@ -5798,6 +5798,7 @@ namespace sol {
// end of sol/inheritance.hpp // end of sol/inheritance.hpp
#include <cmath>
#ifdef SOL_CXX17_FEATURES #ifdef SOL_CXX17_FEATURES
#endif // C++17 #endif // C++17
@ -5854,7 +5855,14 @@ namespace sol {
template <typename Handler> template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
tracking.use(1); tracking.use(1);
bool success = lua_isinteger(L, index) == 1; #if SOL_LUA_VERSION >= 503
if (lua_isinteger(L, index) != 0) {
return true;
}
#endif
int isnum = 0;
const lua_Number v = lua_tonumberx(L, index, &isnum);
const bool success = isnum != 0 && static_cast<lua_Number>(std::llround(v)) == v;
if (!success) { if (!success) {
// expected type, actual type // expected type, actual type
handler(L, index, type::number, type_of(L, index)); handler(L, index, type::number, type_of(L, index));
@ -6347,18 +6355,15 @@ namespace sol {
}; };
template<typename T> template<typename T>
struct getter<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_signed<T>>::value>> { struct getter<T, std::enable_if_t<std::is_integral<T>::value>> {
static T get(lua_State* L, int index, record& tracking) { static T get(lua_State* L, int index, record& tracking) {
tracking.use(1); tracking.use(1);
return static_cast<T>(lua_tointeger(L, index)); #if SOL_LUA_VERSION >= 503
} if (lua_isinteger(L, index) != 0) {
}; return static_cast<T>(lua_tointeger(L, index));
}
template<typename T> #endif
struct getter<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_unsigned<T>>::value>> { return static_cast<T>(std::llround(lua_tonumber(L, index)));
static T get(lua_State* L, int index, record& tracking) {
tracking.use(1);
return static_cast<T>(lua_tointeger(L, index));
} }
}; };
@ -7107,16 +7112,25 @@ namespace sol {
struct check_getter<T, std::enable_if_t<std::is_integral<T>::value && lua_type_of<T>::value == type::number>> { struct check_getter<T, std::enable_if_t<std::is_integral<T>::value && lua_type_of<T>::value == type::number>> {
template <typename Handler> template <typename Handler>
static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) { static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) {
int isnum = 0; #if SOL_LUA_VERSION >= 503
lua_Integer value = lua_tointegerx(L, index, &isnum); if (lua_isinteger(L, index) != 0) {
if (isnum == 0) { tracking.use(1);
type t = type_of(L, index); return static_cast<T>(lua_tointeger(L, index));
tracking.use(static_cast<int>(t != type::none));
handler(L, index, type::number, t);
return nullopt;
} }
tracking.use(1); #endif
return static_cast<T>(value); int isnum = 0;
const lua_Number value = lua_tonumberx(L, index, &isnum);
if (isnum != 0) {
const auto integer_value = std::llround(value);
if (static_cast<lua_Number>(integer_value) == value) {
tracking.use(1);
return static_cast<T>(integer_value);
}
}
const type t = type_of(L, index);
tracking.use(static_cast<int>(t != type::none));
handler(L, index, type::number, t);
return nullopt;
} }
}; };
@ -7317,6 +7331,8 @@ namespace sol {
// end of sol/raii.hpp // end of sol/raii.hpp
#include <cassert>
#include <limits>
#ifdef SOL_CODECVT_SUPPORT #ifdef SOL_CODECVT_SUPPORT
#endif #endif
#ifdef SOL_CXX17_FEATURES #ifdef SOL_CXX17_FEATURES
@ -7477,17 +7493,34 @@ namespace sol {
}; };
template<typename T> template<typename T>
struct pusher<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_signed<T>>::value>> { struct pusher<T, std::enable_if_t<std::is_integral<T>::value>> {
static int push(lua_State* L, const T& value) { static int push(lua_State* L, const T& value) {
lua_pushinteger(L, static_cast<lua_Integer>(value)); #if SOL_LUA_VERSION >= 503
return 1; static auto integer_value_fits = [](T const& value) {
} if (sizeof(T) < sizeof(lua_Integer) || std::is_signed<T>::value && sizeof(T) == sizeof(lua_Integer)) {
}; return true;
}
template<typename T> auto u_min = static_cast<std::intmax_t>(std::numeric_limits<lua_Integer>::min());
struct pusher<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_unsigned<T>>::value>> { auto u_max = static_cast<std::uintmax_t>(std::numeric_limits<lua_Integer>::max());
static int push(lua_State* L, const T& value) { auto t_min = static_cast<std::intmax_t>(std::numeric_limits<T>::min());
lua_pushinteger(L, static_cast<lua_Integer>(value)); auto t_max = static_cast<std::uintmax_t>(std::numeric_limits<T>::max());
return (u_min <= t_min || value >= static_cast<T>(u_min)) && (u_max >= t_max || value <= static_cast<T>(u_max));
};
if (integer_value_fits(value)) {
lua_pushinteger(L, static_cast<lua_Integer>(value));
return 1;
}
#endif
#if defined(SOL_CHECK_ARGUMENTS) && !defined(SOL_NO_CHECK_NUMBER_PRECISION)
if (static_cast<T>(std::llround(static_cast<lua_Number>(value))) != value) {
#ifndef SOL_NO_EXCEPTIONS
throw sol::error("The integer will be misrepresented in lua.");
#else
assert(false && "The integer will be misrepresented in lua.");
#endif
}
#endif
lua_pushnumber(L, static_cast<lua_Number>(value));
return 1; return 1;
} }
}; };
@ -11854,8 +11887,6 @@ namespace sol {
// end of sol/stack_proxy.hpp // end of sol/stack_proxy.hpp
#include <limits>
namespace sol { namespace sol {
template <bool is_const> template <bool is_const>
struct va_iterator : std::iterator<std::random_access_iterator_tag, std::conditional_t<is_const, const stack_proxy, stack_proxy>, std::ptrdiff_t, std::conditional_t<is_const, const stack_proxy*, stack_proxy*>, std::conditional_t<is_const, const stack_proxy, stack_proxy>> { struct va_iterator : std::iterator<std::random_access_iterator_tag, std::conditional_t<is_const, const stack_proxy, stack_proxy>, std::ptrdiff_t, std::conditional_t<is_const, const stack_proxy*, stack_proxy*>, std::conditional_t<is_const, const stack_proxy, stack_proxy>> {
@ -13716,7 +13747,6 @@ namespace sol {
#include <cstdio> #include <cstdio>
#include <sstream> #include <sstream>
#include <cassert>
namespace sol { namespace sol {
namespace usertype_detail { namespace usertype_detail {

View File

@ -28,6 +28,7 @@
#include <memory> #include <memory>
#include <functional> #include <functional>
#include <utility> #include <utility>
#include <cmath>
#ifdef SOL_CXX17_FEATURES #ifdef SOL_CXX17_FEATURES
#include <variant> #include <variant>
#endif // C++17 #endif // C++17
@ -85,7 +86,14 @@ namespace sol {
template <typename Handler> template <typename Handler>
static bool check(lua_State* L, int index, Handler&& handler, record& tracking) { static bool check(lua_State* L, int index, Handler&& handler, record& tracking) {
tracking.use(1); tracking.use(1);
bool success = lua_isinteger(L, index) == 1; #if SOL_LUA_VERSION >= 503
if (lua_isinteger(L, index) != 0) {
return true;
}
#endif
int isnum = 0;
const lua_Number v = lua_tonumberx(L, index, &isnum);
const bool success = isnum != 0 && static_cast<lua_Number>(std::llround(v)) == v;
if (!success) { if (!success) {
// expected type, actual type // expected type, actual type
handler(L, index, type::number, type_of(L, index)); handler(L, index, type::number, type_of(L, index));

View File

@ -27,6 +27,7 @@
#include "stack_check.hpp" #include "stack_check.hpp"
#include "optional.hpp" #include "optional.hpp"
#include <cstdlib> #include <cstdlib>
#include <cmath>
namespace sol { namespace sol {
namespace stack { namespace stack {
@ -56,16 +57,25 @@ namespace sol {
struct check_getter<T, std::enable_if_t<std::is_integral<T>::value && lua_type_of<T>::value == type::number>> { struct check_getter<T, std::enable_if_t<std::is_integral<T>::value && lua_type_of<T>::value == type::number>> {
template <typename Handler> template <typename Handler>
static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) { static optional<T> get(lua_State* L, int index, Handler&& handler, record& tracking) {
int isnum = 0; #if SOL_LUA_VERSION >= 503
lua_Integer value = lua_tointegerx(L, index, &isnum); if (lua_isinteger(L, index) != 0) {
if (isnum == 0) { tracking.use(1);
type t = type_of(L, index); return static_cast<T>(lua_tointeger(L, index));
tracking.use(static_cast<int>(t != type::none));
handler(L, index, type::number, t);
return nullopt;
} }
tracking.use(1); #endif
return static_cast<T>(value); int isnum = 0;
const lua_Number value = lua_tonumberx(L, index, &isnum);
if (isnum != 0) {
const auto integer_value = std::llround(value);
if (static_cast<lua_Number>(integer_value) == value) {
tracking.use(1);
return static_cast<T>(integer_value);
}
}
const type t = type_of(L, index);
tracking.use(static_cast<int>(t != type::none));
handler(L, index, type::number, t);
return nullopt;
} }
}; };

View File

@ -31,6 +31,7 @@
#include <functional> #include <functional>
#include <utility> #include <utility>
#include <cstdlib> #include <cstdlib>
#include <cmath>
#ifdef SOL_CODECVT_SUPPORT #ifdef SOL_CODECVT_SUPPORT
#include <codecvt> #include <codecvt>
#include <locale> #include <locale>
@ -59,18 +60,15 @@ namespace sol {
}; };
template<typename T> template<typename T>
struct getter<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_signed<T>>::value>> { struct getter<T, std::enable_if_t<std::is_integral<T>::value>> {
static T get(lua_State* L, int index, record& tracking) { static T get(lua_State* L, int index, record& tracking) {
tracking.use(1); tracking.use(1);
return static_cast<T>(lua_tointeger(L, index)); #if SOL_LUA_VERSION >= 503
} if (lua_isinteger(L, index) != 0) {
}; return static_cast<T>(lua_tointeger(L, index));
}
template<typename T> #endif
struct getter<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_unsigned<T>>::value>> { return static_cast<T>(std::llround(lua_tonumber(L, index)));
static T get(lua_State* L, int index, record& tracking) {
tracking.use(1);
return static_cast<T>(lua_tointeger(L, index));
} }
}; };

View File

@ -28,6 +28,8 @@
#include "usertype_traits.hpp" #include "usertype_traits.hpp"
#include <memory> #include <memory>
#include <type_traits> #include <type_traits>
#include <cassert>
#include <limits>
#ifdef SOL_CODECVT_SUPPORT #ifdef SOL_CODECVT_SUPPORT
#include <codecvt> #include <codecvt>
#include <locale> #include <locale>
@ -192,17 +194,34 @@ namespace sol {
}; };
template<typename T> template<typename T>
struct pusher<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_signed<T>>::value>> { struct pusher<T, std::enable_if_t<std::is_integral<T>::value>> {
static int push(lua_State* L, const T& value) { static int push(lua_State* L, const T& value) {
lua_pushinteger(L, static_cast<lua_Integer>(value)); #if SOL_LUA_VERSION >= 503
return 1; static auto integer_value_fits = [](T const& value) {
} if (sizeof(T) < sizeof(lua_Integer) || std::is_signed<T>::value && sizeof(T) == sizeof(lua_Integer)) {
}; return true;
}
template<typename T> auto u_min = static_cast<std::intmax_t>(std::numeric_limits<lua_Integer>::min());
struct pusher<T, std::enable_if_t<meta::all<std::is_integral<T>, std::is_unsigned<T>>::value>> { auto u_max = static_cast<std::uintmax_t>(std::numeric_limits<lua_Integer>::max());
static int push(lua_State* L, const T& value) { auto t_min = static_cast<std::intmax_t>(std::numeric_limits<T>::min());
lua_pushinteger(L, static_cast<lua_Integer>(value)); auto t_max = static_cast<std::uintmax_t>(std::numeric_limits<T>::max());
return (u_min <= t_min || value >= static_cast<T>(u_min)) && (u_max >= t_max || value <= static_cast<T>(u_max));
};
if (integer_value_fits(value)) {
lua_pushinteger(L, static_cast<lua_Integer>(value));
return 1;
}
#endif
#if defined(SOL_CHECK_ARGUMENTS) && !defined(SOL_NO_CHECK_NUMBER_PRECISION)
if (static_cast<T>(std::llround(static_cast<lua_Number>(value))) != value) {
#ifndef SOL_NO_EXCEPTIONS
throw sol::error("The integer will be misrepresented in lua.");
#else
assert(false && "The integer will be misrepresented in lua.");
#endif
}
#endif
lua_pushnumber(L, static_cast<lua_Number>(value));
return 1; return 1;
} }
}; };

117
test_large_integer.cpp Normal file
View File

@ -0,0 +1,117 @@
#define SOL_CHECK_ARGUMENTS
#include <sol.hpp>
#include <catch.hpp>
#include <cstdint>
#include <limits>
TEST_CASE("large_integer/bool", "pass bool integral value to and from lua") {
sol::state lua;
lua.open_libraries();
lua.set_function("f", [&](bool num) {
REQUIRE(num == true);
return num;
});
lua.script("x = f(true)");
lua.script("assert(x == true)");
sol::object x = lua["x"];
REQUIRE(x.is<bool>());
REQUIRE(x.as<bool>() == true);
REQUIRE_FALSE(x.is<std::int32_t>());
REQUIRE_THROWS([&lua]() {
lua.script("f(1)");
}());
}
TEST_CASE("large_integers/unsigned32", "pass large unsigned 32bit values to and from lua") {
using T = std::uint32_t;
sol::state lua;
lua.open_libraries();
lua.set_function("f", [&](T num) -> T {
REQUIRE(num == 0xFFFFFFFF);
return num;
});
lua.script("x = f(0xFFFFFFFF)");
lua.script("assert(x == 0xFFFFFFFF)");
sol::object x = lua["x"];
REQUIRE(x.is<T>());
REQUIRE(x.as<T>() == 0xFFFFFFFF);
}
TEST_CASE("large_integer/unsigned53", "pass large unsigned 53bit value to and from lua") {
using T = std::uint64_t;
sol::state lua;
lua.open_libraries();
lua.set_function("f", [&](T num) -> T {
REQUIRE(num == 0x1FFFFFFFFFFFFFull);
return num;
});
lua.script("x = f(0x1FFFFFFFFFFFFF)");
lua.script("assert(x == 0x1FFFFFFFFFFFFF)");
sol::object x = lua["x"];
REQUIRE(x.is<T>());
REQUIRE(x.as<T>() == 0x1FFFFFFFFFFFFFull);
}
TEST_CASE("large_integer/unsigned64", "pass too large unsigned 64bit value to lua") {
using T = std::int64_t;
sol::state lua;
lua.open_libraries();
lua.set_function("f", [&](T num) -> T {
return num;
});
REQUIRE_THROWS([&lua]() {
lua["f"](0xFFFFFFFFFFFFFFFFull);
}());
}
TEST_CASE("large_integer/double", "pass negative and large positive values as signed and unsigned from and to lua") {
sol::state lua;
lua.open_libraries();
lua.set_function("s32", [&](std::int32_t num) {
return num;
});
lua.set_function("s64", [&](std::int64_t num) {
return num;
});
lua.set_function("u32", [&](std::uint32_t num) {
return num;
});
lua.set_function("u64", [&](std::uint64_t num) {
return num;
});
//signed 32bit
REQUIRE_NOTHROW([&lua]() {
lua.script("x = s32(-1)");
lua.script("assert(x == -1)");
lua.script("x = s32(0xFFFFFFFF)");
lua.script("assert(x == -1)");
sol::object x = lua["x"];
REQUIRE(x.is<std::int32_t>());
REQUIRE(x.as<std::int32_t>() == -1);
REQUIRE(x.is<std::uint32_t>());
REQUIRE(x.as<std::uint32_t>() == 0xFFFFFFFF);
}());
//unsigned 32bit
REQUIRE_NOTHROW([&lua]() {
lua.script("x = u32(0xFFFFFFFF)");
lua.script("assert(x == 0xFFFFFFFF)");
lua.script("x = u32(-1)");
lua.script("assert(x == 0xFFFFFFFF)");
sol::object x = lua["x"];
REQUIRE(x.is<std::int32_t>());
REQUIRE(x.as<std::int32_t>() == -1);
REQUIRE(x.is<std::uint32_t>());
REQUIRE(x.as<std::uint32_t>() == 0xFFFFFFFF);
}());
//signed 64bit
REQUIRE_NOTHROW([&lua]() {
lua.script("x = s64(-1)");
lua.script("assert(x == -1)");
sol::object x = lua["x"];
REQUIRE(x.is<std::int64_t>());
REQUIRE(x.as<std::int64_t>() == -1);
REQUIRE(x.is<std::uint64_t>());
REQUIRE(x.as<std::uint64_t>() == 0xFFFFFFFFFFFFFFFFull);
}());
}