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 detail {
|
||||
#ifndef SOL_NO_RTTI
|
||||
#ifdef _MSC_VER
|
||||
#ifndef SOL_NO_RTTI
|
||||
inline std::string get_type_name(const std::type_info& id) {
|
||||
return id.name();
|
||||
}
|
||||
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
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);
|
||||
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) {
|
||||
auto found = realname.find(removals[r]);
|
||||
while (found != std::string::npos) {
|
||||
realname.erase(found, removals[r].size());
|
||||
found = realname.find(removals[r]);
|
||||
}
|
||||
}
|
||||
return realname;
|
||||
}
|
||||
|
||||
#else
|
||||
#error Compiler not supported for demangling
|
||||
#endif // compilers
|
||||
#else
|
||||
#ifdef _MSC_VER
|
||||
#endif // No RTII
|
||||
template <typename T>
|
||||
inline std::string get_type_name() {
|
||||
inline std::string ctti_get_type_name() {
|
||||
std::string name = __FUNCSIG__;
|
||||
std::size_t start = name.find("get_type_name");
|
||||
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());
|
||||
return name;
|
||||
}
|
||||
|
||||
#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>
|
||||
inline std::string get_type_name() {
|
||||
inline std::string ctti_get_type_name() {
|
||||
std::string name = __PRETTY_FUNCTION__;
|
||||
std::size_t start = name.find_first_of('=');
|
||||
std::size_t end = name.find_last_of(';');
|
||||
|
@ -92,8 +95,17 @@ inline std::string get_type_name() {
|
|||
return name;
|
||||
}
|
||||
#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>
|
||||
inline std::string get_type_name() {
|
||||
inline std::string ctti_get_type_name() {
|
||||
std::string name = __PRETTY_FUNCTION__;
|
||||
std::size_t start = name.find_last_of('[');
|
||||
start = name.find_first_of('=', start);
|
||||
|
@ -107,36 +119,28 @@ inline std::string get_type_name() {
|
|||
name = name.substr(start, end - start);
|
||||
return name;
|
||||
}
|
||||
|
||||
#else
|
||||
#error Compiler not supported for demangling
|
||||
#endif // compilers
|
||||
#endif // No Runtime Type information
|
||||
|
||||
template <typename T>
|
||||
inline std::string demangle_once() {
|
||||
#ifndef SOL_NO_RTTI
|
||||
std::string realname = get_type_name(typeid(T));
|
||||
#else
|
||||
std::string realname = get_type_name<T>();
|
||||
std::string realname = ctti_get_type_name<T>();
|
||||
#endif // No Runtime Type Information
|
||||
const static std::array<std::string, 2> removals = {{ "struct ", "class " }};
|
||||
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]);
|
||||
}
|
||||
}
|
||||
return realname;
|
||||
}
|
||||
|
||||
for(std::size_t r = 0; r < replacements.size(); r+=2) {
|
||||
auto found = realname.find(replacements[r]);
|
||||
while(found != std::string::npos) {
|
||||
realname.replace(found, replacements[r].size(), replacements[r + 1]);
|
||||
found = realname.find(replacements[r], found);
|
||||
}
|
||||
template <typename T>
|
||||
inline std::string short_demangle_once() {
|
||||
std::string realname = ctti_get_type_name<T>();
|
||||
std::size_t idx = realname.find_last_of(":`'\"{}[]|-)(*^&!@#$%`~", std::string::npos, 23);
|
||||
if (idx != std::string::npos) {
|
||||
realname.erase(0, realname.length() < idx ? realname.length() : idx + 1);
|
||||
}
|
||||
|
||||
return realname;
|
||||
}
|
||||
|
||||
|
@ -145,6 +149,12 @@ inline std::string demangle() {
|
|||
static const std::string d = demangle_once<T>();
|
||||
return d;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline std::string short_demangle() {
|
||||
static const std::string d = short_demangle_once<T>();
|
||||
return d;
|
||||
}
|
||||
} // detail
|
||||
} // 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>
|
||||
struct checker<T, type::userdata, C> {
|
||||
template <typename U, typename Handler>
|
||||
|
|
|
@ -44,7 +44,7 @@ struct pusher {
|
|||
referencereference = allocationtarget;
|
||||
std::allocator<T> alloc{};
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -449,6 +449,7 @@ private:
|
|||
template<typename... Args>
|
||||
usertype(usertype_detail::verified_tag, Args&&... args) : indexfunc(nullptr), newindexfunc(nullptr), constructfunc(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);
|
||||
functiontable.reserve(sizeof...(args)+3);
|
||||
metafunctiontable.reserve(sizeof...(args)+3);
|
||||
|
|
|
@ -29,13 +29,17 @@ namespace sol {
|
|||
template<typename T>
|
||||
struct usertype_traits {
|
||||
static const std::string name;
|
||||
static const std::string qualified_name;
|
||||
static const std::string metatable;
|
||||
static const std::string variable_metatable;
|
||||
static const std::string gc_table;
|
||||
};
|
||||
|
||||
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>
|
||||
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.script(
|
||||
"a = crapola_fuser.new(2)\n"
|
||||
"a = fuser.new(2)\n"
|
||||
"u = a:add(1)\n"
|
||||
"v = a:add2(1)\n"
|
||||
"b = crapola_fuser:new()\n"
|
||||
"b = fuser:new()\n"
|
||||
"w = b:add(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"
|
||||
"z = c:add2(1)\n");
|
||||
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"
|
||||
"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") {
|
||||
|
|
Loading…
Reference in New Issue
Block a user