mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
Better demangling
Userdata pushed before the usertype is pushed will not latch onto the new metatable if its added Updated tests
This commit is contained in:
parent
96da27d565
commit
2cfe74cc7f
|
@ -33,28 +33,23 @@
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
#ifndef SOL_NO_RTTI
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
#ifndef SOL_NO_RTTI
|
||||||
inline std::string get_type_name(const std::type_info& id) {
|
inline std::string get_type_name(const std::type_info& id) {
|
||||||
return id.name();
|
std::string realname = id.name();
|
||||||
}
|
const static std::array<std::string, 2> removals = { { "struct ", "class " } };
|
||||||
|
for (std::size_t r = 0; r < removals.size(); ++r) {
|
||||||
#elif defined(__GNUC__) || defined(__clang__)
|
auto found = realname.find(removals[r]);
|
||||||
inline std::string get_type_name(const std::type_info& id) {
|
while (found != std::string::npos) {
|
||||||
int status;
|
realname.erase(found, removals[r].size());
|
||||||
char* unmangled = abi::__cxa_demangle(id.name(), 0, 0, &status);
|
found = realname.find(removals[r]);
|
||||||
std::string realname = unmangled;
|
}
|
||||||
std::free(unmangled);
|
}
|
||||||
return realname;
|
return realname;
|
||||||
}
|
}
|
||||||
|
#endif // No RTII
|
||||||
#else
|
|
||||||
#error Compiler not supported for demangling
|
|
||||||
#endif // compilers
|
|
||||||
#else
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline std::string get_type_name() {
|
inline std::string ctti_get_type_name() {
|
||||||
std::string name = __FUNCSIG__;
|
std::string name = __FUNCSIG__;
|
||||||
std::size_t start = name.find("get_type_name");
|
std::size_t start = name.find("get_type_name");
|
||||||
if (start == std::string::npos)
|
if (start == std::string::npos)
|
||||||
|
@ -75,10 +70,18 @@ inline std::string get_type_name() {
|
||||||
while (name.size() > 0 && std::isblank(name.back())) name.erase(--name.end(), name.end());
|
while (name.size() > 0 && std::isblank(name.back())) name.erase(--name.end(), name.end());
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
|
#ifndef SOL_NO_RTTI
|
||||||
|
inline std::string get_type_name(const std::type_info& id) {
|
||||||
|
int status;
|
||||||
|
char* unmangled = abi::__cxa_demangle(id.name(), 0, 0, &status);
|
||||||
|
std::string realname = unmangled;
|
||||||
|
std::free(unmangled);
|
||||||
|
return realname;
|
||||||
|
}
|
||||||
|
#endif // No RTII
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline std::string get_type_name() {
|
inline std::string ctti_get_type_name() {
|
||||||
std::string name = __PRETTY_FUNCTION__;
|
std::string name = __PRETTY_FUNCTION__;
|
||||||
std::size_t start = name.find_first_of('=');
|
std::size_t start = name.find_first_of('=');
|
||||||
std::size_t end = name.find_last_of(';');
|
std::size_t end = name.find_last_of(';');
|
||||||
|
@ -92,8 +95,17 @@ inline std::string get_type_name() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
#elif defined(__clang__)
|
#elif defined(__clang__)
|
||||||
|
#ifndef SOL_NO_RTTI
|
||||||
|
inline std::string get_type_name(const std::type_info& id) {
|
||||||
|
int status;
|
||||||
|
char* unmangled = abi::__cxa_demangle(id.name(), 0, 0, &status);
|
||||||
|
std::string realname = unmangled;
|
||||||
|
std::free(unmangled);
|
||||||
|
return realname;
|
||||||
|
}
|
||||||
|
#endif // No RTII
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline std::string get_type_name() {
|
inline std::string ctti_get_type_name() {
|
||||||
std::string name = __PRETTY_FUNCTION__;
|
std::string name = __PRETTY_FUNCTION__;
|
||||||
std::size_t start = name.find_last_of('[');
|
std::size_t start = name.find_last_of('[');
|
||||||
start = name.find_first_of('=', start);
|
start = name.find_first_of('=', start);
|
||||||
|
@ -107,36 +119,28 @@ inline std::string get_type_name() {
|
||||||
name = name.substr(start, end - start);
|
name = name.substr(start, end - start);
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error Compiler not supported for demangling
|
#error Compiler not supported for demangling
|
||||||
#endif // compilers
|
#endif // compilers
|
||||||
#endif // No Runtime Type information
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline std::string demangle_once() {
|
inline std::string demangle_once() {
|
||||||
#ifndef SOL_NO_RTTI
|
#ifndef SOL_NO_RTTI
|
||||||
std::string realname = get_type_name(typeid(T));
|
std::string realname = get_type_name(typeid(T));
|
||||||
#else
|
#else
|
||||||
std::string realname = get_type_name<T>();
|
std::string realname = ctti_get_type_name<T>();
|
||||||
#endif // No Runtime Type Information
|
#endif // No Runtime Type Information
|
||||||
const static std::array<std::string, 2> removals = {{ "struct ", "class " }};
|
return realname;
|
||||||
const static std::array<std::string, 2> replacements = {{ "::", "_" }};
|
}
|
||||||
for(std::size_t r = 0; r < removals.size(); ++r) {
|
|
||||||
auto found = realname.find(removals[r]);
|
|
||||||
while(found != std::string::npos) {
|
|
||||||
realname.erase(found, removals[r].size());
|
|
||||||
found = realname.find(removals[r]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(std::size_t r = 0; r < replacements.size(); r+=2) {
|
template <typename T>
|
||||||
auto found = realname.find(replacements[r]);
|
inline std::string short_demangle_once() {
|
||||||
while(found != std::string::npos) {
|
std::string realname = ctti_get_type_name<T>();
|
||||||
realname.replace(found, replacements[r].size(), replacements[r + 1]);
|
std::size_t idx = realname.find_last_of(":`'\"{}[]|-)(*^&!@#$%`~", std::string::npos, 23);
|
||||||
found = realname.find(replacements[r], found);
|
if (idx != std::string::npos) {
|
||||||
|
realname.erase(0, realname.length() < idx ? realname.length() : idx + 1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return realname;
|
return realname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,6 +149,12 @@ inline std::string demangle() {
|
||||||
static const std::string d = demangle_once<T>();
|
static const std::string d = demangle_once<T>();
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline std::string short_demangle() {
|
||||||
|
static const std::string d = short_demangle_once<T>();
|
||||||
|
return d;
|
||||||
|
}
|
||||||
} // detail
|
} // detail
|
||||||
} // sol
|
} // sol
|
||||||
|
|
||||||
|
|
|
@ -235,6 +235,20 @@ struct checker<T*, type::userdata, C> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename C>
|
||||||
|
struct checker<userdata_value, type::userdata, C> {
|
||||||
|
template <typename Handler>
|
||||||
|
static bool check(lua_State* L, int index, Handler&& handler) {
|
||||||
|
type t = type_of(L, index);
|
||||||
|
bool success = t == type::userdata || t == type::lightuserdata;
|
||||||
|
if (!success) {
|
||||||
|
// expected type, actual type
|
||||||
|
handler(L, index, type::lightuserdata, t);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T, typename C>
|
template <typename T, typename C>
|
||||||
struct checker<T, type::userdata, C> {
|
struct checker<T, type::userdata, C> {
|
||||||
template <typename U, typename Handler>
|
template <typename U, typename Handler>
|
||||||
|
|
|
@ -44,7 +44,7 @@ struct pusher {
|
||||||
referencereference = allocationtarget;
|
referencereference = allocationtarget;
|
||||||
std::allocator<T> alloc{};
|
std::allocator<T> alloc{};
|
||||||
alloc.construct(allocationtarget, std::forward<Args>(args)...);
|
alloc.construct(allocationtarget, std::forward<Args>(args)...);
|
||||||
luaL_getmetatable(L, &usertype_traits<T>::metatable[0]);
|
luaL_newmetatable(L, &usertype_traits<T>::metatable[0]);
|
||||||
lua_setmetatable(L, -2);
|
lua_setmetatable(L, -2);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -449,6 +449,7 @@ private:
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
usertype(usertype_detail::verified_tag, Args&&... args) : indexfunc(nullptr), newindexfunc(nullptr), constructfunc(nullptr),
|
usertype(usertype_detail::verified_tag, Args&&... args) : indexfunc(nullptr), newindexfunc(nullptr), constructfunc(nullptr),
|
||||||
destructfunc(nullptr), functiongcfunc(nullptr), needsindexfunction(false), baseclasscheck(nullptr), baseclasscast(nullptr) {
|
destructfunc(nullptr), functiongcfunc(nullptr), needsindexfunction(false), baseclasscheck(nullptr), baseclasscast(nullptr) {
|
||||||
|
static_assert((sizeof...(Args) % 2) == 0, "incorrect pairing of arguments to usertype creation: maybe forgotten comma somewhere");
|
||||||
functionnames.reserve(sizeof...(args)+3);
|
functionnames.reserve(sizeof...(args)+3);
|
||||||
functiontable.reserve(sizeof...(args)+3);
|
functiontable.reserve(sizeof...(args)+3);
|
||||||
metafunctiontable.reserve(sizeof...(args)+3);
|
metafunctiontable.reserve(sizeof...(args)+3);
|
||||||
|
|
|
@ -29,13 +29,17 @@ namespace sol {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct usertype_traits {
|
struct usertype_traits {
|
||||||
static const std::string name;
|
static const std::string name;
|
||||||
|
static const std::string qualified_name;
|
||||||
static const std::string metatable;
|
static const std::string metatable;
|
||||||
static const std::string variable_metatable;
|
static const std::string variable_metatable;
|
||||||
static const std::string gc_table;
|
static const std::string gc_table;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const std::string usertype_traits<T>::name = detail::demangle<T>();
|
const std::string usertype_traits<T>::name = detail::short_demangle<T>();
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
const std::string usertype_traits<T>::qualified_name = detail::demangle<T>();
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const std::string usertype_traits<T>::metatable = std::string("sol.").append(detail::demangle<T>());
|
const std::string usertype_traits<T>::metatable = std::string("sol.").append(detail::demangle<T>());
|
||||||
|
|
21
tests.cpp
21
tests.cpp
|
@ -408,13 +408,13 @@ TEST_CASE("usertype/usertype-constructors", "Show that we can create classes fro
|
||||||
lua.set_usertype(lc);
|
lua.set_usertype(lc);
|
||||||
|
|
||||||
lua.script(
|
lua.script(
|
||||||
"a = crapola_fuser.new(2)\n"
|
"a = fuser.new(2)\n"
|
||||||
"u = a:add(1)\n"
|
"u = a:add(1)\n"
|
||||||
"v = a:add2(1)\n"
|
"v = a:add2(1)\n"
|
||||||
"b = crapola_fuser:new()\n"
|
"b = fuser:new()\n"
|
||||||
"w = b:add(1)\n"
|
"w = b:add(1)\n"
|
||||||
"x = b:add2(1)\n"
|
"x = b:add2(1)\n"
|
||||||
"c = crapola_fuser.new(2, 3)\n"
|
"c = fuser.new(2, 3)\n"
|
||||||
"y = c:add(1)\n"
|
"y = c:add(1)\n"
|
||||||
"z = c:add2(1)\n");
|
"z = c:add2(1)\n");
|
||||||
sol::object a = lua.get<sol::object>("a");
|
sol::object a = lua.get<sol::object>("a");
|
||||||
|
@ -615,6 +615,21 @@ TEST_CASE("usertype/member-variables", "allow table-like accessors to behave as
|
||||||
"local x = v.x\n"
|
"local x = v.x\n"
|
||||||
"assert(x == 3)\n"
|
"assert(x == 3)\n"
|
||||||
));
|
));
|
||||||
|
|
||||||
|
struct breaks {
|
||||||
|
sol::function f;
|
||||||
|
};
|
||||||
|
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
lua.set("b", breaks());
|
||||||
|
lua.new_usertype<breaks>("breaks",
|
||||||
|
"f", &breaks::f
|
||||||
|
);
|
||||||
|
|
||||||
|
breaks& b = lua["b"];
|
||||||
|
REQUIRE_NOTHROW(lua.script("b.f = function () print('BARK!') end"));
|
||||||
|
REQUIRE_NOTHROW(lua.script("b.f()"));
|
||||||
|
REQUIRE_NOTHROW(b.f());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("usertype/nonmember-functions", "let users set non-member functions that take unqualified T as first parameter to usertype") {
|
TEST_CASE("usertype/nonmember-functions", "let users set non-member functions that take unqualified T as first parameter to usertype") {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user