mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
BREAKING CHANGE: std::pair
for regular containers that are not marked as as_table_t
or as_nested
will now behave like regular containers and not force themselves to be key-value pairs. table-style serialization is still unaffected.
This commit is contained in:
parent
6b34a15d68
commit
17271c84cb
|
@ -77,6 +77,7 @@ Based on the type pushed, a few additional functions are added as "member functi
|
||||||
* ``my_container:add( key, value )`` or ``my_container:add( value )``: this will add to the end of the container, or if it is an associative or ordered container, simply put in an expected key-value pair into it.
|
* ``my_container:add( key, value )`` or ``my_container:add( value )``: this will add to the end of the container, or if it is an associative or ordered container, simply put in an expected key-value pair into it.
|
||||||
* ``my_contaner:insert( where, value )`` or ``my_contaner:insert( key, value )``: similar to add, but it only takes two arguments. In the case of ``std::vector`` and the like, the first argument is a ``where`` integer index. The second argument is the value. For associative containers, a key and value argument are expected.
|
* ``my_contaner:insert( where, value )`` or ``my_contaner:insert( key, value )``: similar to add, but it only takes two arguments. In the case of ``std::vector`` and the like, the first argument is a ``where`` integer index. The second argument is the value. For associative containers, a key and value argument are expected.
|
||||||
* ``my_container:find( value )``: This will call the underlying containers ``find`` function if it exists, or in case of associative containers, it will work just like an index call. This is meant to give a fast membership check for ``std::set`` and ``std::unordered_set`` containers.
|
* ``my_container:find( value )``: This will call the underlying containers ``find`` function if it exists, or in case of associative containers, it will work just like an index call. This is meant to give a fast membership check for ``std::set`` and ``std::unordered_set`` containers.
|
||||||
|
* ``my_container:get( key )``: This function can return multiple values when the value type is a ``std::pair`` or ``std::tuple``, which is not the case for ``obj[key]``! This will call the underlying containers ``find`` function if it exists, index into a regular container, or in case of certain associative containers, it will work just like an index call. This is meant to give a fast membership check for ``std::set`` and ``std::unordered_set`` containers.
|
||||||
|
|
||||||
.. _container-detection:
|
.. _container-detection:
|
||||||
|
|
||||||
|
|
|
@ -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-06-20 03:06:38.649640 UTC
|
// Generated 2017-06-23 22:06:34.237732 UTC
|
||||||
// This header was generated with sol v2.17.5 (revision 5468ab8)
|
// This header was generated with sol v2.17.5 (revision 6b34a15)
|
||||||
// https://github.com/ThePhD/sol2
|
// https://github.com/ThePhD/sol2
|
||||||
|
|
||||||
#ifndef SOL_SINGLE_INCLUDE_HPP
|
#ifndef SOL_SINGLE_INCLUDE_HPP
|
||||||
|
@ -829,6 +829,24 @@ namespace sol {
|
||||||
static std::false_type test(...);
|
static std::false_type test(...);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct has_key_type_impl {
|
||||||
|
template<typename T, typename U = unqualified_t<T>,
|
||||||
|
typename V = typename U::key_type>
|
||||||
|
static std::true_type test(int);
|
||||||
|
|
||||||
|
template<typename...>
|
||||||
|
static std::false_type test(...);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct has_mapped_type_impl {
|
||||||
|
template<typename T, typename U = unqualified_t<T>,
|
||||||
|
typename V = typename U::mapped_type>
|
||||||
|
static std::true_type test(int);
|
||||||
|
|
||||||
|
template<typename...>
|
||||||
|
static std::false_type test(...);
|
||||||
|
};
|
||||||
|
|
||||||
struct has_key_value_pair_impl {
|
struct has_key_value_pair_impl {
|
||||||
template<typename T, typename U = unqualified_t<T>,
|
template<typename T, typename U = unqualified_t<T>,
|
||||||
typename V = typename U::value_type,
|
typename V = typename U::value_type,
|
||||||
|
@ -868,6 +886,15 @@ namespace sol {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test<T>(0)) {};
|
struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test<T>(0)) {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct has_key_type : decltype(meta_detail::has_key_type_impl::test<T>(0)) {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct has_mapped_type : decltype(meta_detail::has_mapped_type_impl::test<T>(0)) {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_associative : meta::all<has_key_value_pair<T>, has_mapped_type<T>> {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using is_string_constructible = any<std::is_same<unqualified_t<T>, const char*>, std::is_same<unqualified_t<T>, char>, std::is_same<unqualified_t<T>, std::string>, std::is_same<unqualified_t<T>, std::initializer_list<char>>>;
|
using is_string_constructible = any<std::is_same<unqualified_t<T>, const char*>, std::is_same<unqualified_t<T>, char>, std::is_same<unqualified_t<T>, std::string>, std::is_same<unqualified_t<T>, std::initializer_list<char>>>;
|
||||||
|
|
||||||
|
@ -3541,6 +3568,11 @@ namespace sol {
|
||||||
return as_table_t<T>(std::forward<T>(container));
|
return as_table_t<T>(std::forward<T>(container));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
nested<T> as_nested(T&& container) {
|
||||||
|
return as_nested<T>(std::forward<T>(container));
|
||||||
|
}
|
||||||
|
|
||||||
struct this_state {
|
struct this_state {
|
||||||
lua_State* L;
|
lua_State* L;
|
||||||
operator lua_State* () const {
|
operator lua_State* () const {
|
||||||
|
@ -12520,7 +12552,7 @@ namespace sol {
|
||||||
|
|
||||||
template <typename Raw, typename C = void>
|
template <typename Raw, typename C = void>
|
||||||
struct container_usertype_metatable {
|
struct container_usertype_metatable {
|
||||||
typedef meta::has_key_value_pair<meta::unqualified_t<Raw>> is_associative;
|
typedef meta::is_associative<std::remove_pointer_t<meta::unqualified_t<Raw>>> is_associative;
|
||||||
typedef meta::unqualified_t<Raw> T;
|
typedef meta::unqualified_t<Raw> T;
|
||||||
typedef typename T::iterator I;
|
typedef typename T::iterator I;
|
||||||
typedef std::conditional_t<is_associative::value, typename T::value_type, std::pair<std::size_t, typename T::value_type>> KV;
|
typedef std::conditional_t<is_associative::value, typename T::value_type, std::pair<std::size_t, typename T::value_type>> KV;
|
||||||
|
@ -12555,6 +12587,25 @@ namespace sol {
|
||||||
#endif // Safe getting with error
|
#endif // Safe getting with error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int delegate_call(lua_State* L) {
|
||||||
|
static std::unordered_map<std::string, lua_CFunction> calls{
|
||||||
|
{ "add", &real_add_call },
|
||||||
|
{ "insert", &real_insert_call },
|
||||||
|
{ "clear", &real_clear_call },
|
||||||
|
{ "find", &real_find_call },
|
||||||
|
{ "get", &real_get_call }
|
||||||
|
};
|
||||||
|
auto maybename = stack::check_get<std::string>(L, 2);
|
||||||
|
if (maybename) {
|
||||||
|
auto& name = *maybename;
|
||||||
|
auto it = calls.find(name);
|
||||||
|
if (it != calls.cend()) {
|
||||||
|
return stack::push(L, it->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stack::push(L, lua_nil);
|
||||||
|
}
|
||||||
|
|
||||||
static int real_index_call_associative(std::true_type, lua_State* L) {
|
static int real_index_call_associative(std::true_type, lua_State* L) {
|
||||||
auto k = stack::check_get<K>(L, 2);
|
auto k = stack::check_get<K>(L, 2);
|
||||||
if (k) {
|
if (k) {
|
||||||
|
@ -12567,22 +12618,7 @@ namespace sol {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto maybename = stack::check_get<string_detail::string_shim>(L, 2);
|
return delegate_call(L);
|
||||||
if (maybename) {
|
|
||||||
auto& name = *maybename;
|
|
||||||
if (name == "add") {
|
|
||||||
return stack::push(L, &add_call);
|
|
||||||
}
|
|
||||||
else if (name == "insert") {
|
|
||||||
return stack::push(L, &insert_call);
|
|
||||||
}
|
|
||||||
else if (name == "clear") {
|
|
||||||
return stack::push(L, &clear_call);
|
|
||||||
}
|
|
||||||
else if (name == "find") {
|
|
||||||
return stack::push(L, &find_call);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return stack::push(L, lua_nil);
|
return stack::push(L, lua_nil);
|
||||||
}
|
}
|
||||||
|
@ -12602,22 +12638,7 @@ namespace sol {
|
||||||
return stack::stack_detail::push_reference<push_type>(L, *it);
|
return stack::stack_detail::push_reference<push_type>(L, *it);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto maybename = stack::check_get<string_detail::string_shim>(L, 2);
|
return delegate_call(L);
|
||||||
if (maybename) {
|
|
||||||
auto& name = *maybename;
|
|
||||||
if (name == "add") {
|
|
||||||
return stack::push(L, &add_call);
|
|
||||||
}
|
|
||||||
else if (name == "insert") {
|
|
||||||
return stack::push(L, &insert_call);
|
|
||||||
}
|
|
||||||
else if (name == "clear") {
|
|
||||||
return stack::push(L, &clear_call);
|
|
||||||
}
|
|
||||||
else if (name == "find") {
|
|
||||||
return stack::push(L, &find_call);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return stack::push(L, lua_nil);
|
return stack::push(L, lua_nil);
|
||||||
|
@ -12627,6 +12648,10 @@ namespace sol {
|
||||||
return real_index_call_associative(is_associative(), L);
|
return real_index_call_associative(is_associative(), L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int real_get_call(lua_State* L) {
|
||||||
|
return real_index_call_associative(is_associative(), L);
|
||||||
|
}
|
||||||
|
|
||||||
static int real_new_index_call_const(std::false_type, std::false_type, lua_State* L) {
|
static int real_new_index_call_const(std::false_type, std::false_type, lua_State* L) {
|
||||||
return luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)");
|
return luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)");
|
||||||
}
|
}
|
||||||
|
@ -12635,12 +12660,12 @@ namespace sol {
|
||||||
return luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)");
|
return luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int real_new_index_call_const(std::true_type, std::true_type, lua_State* L) {
|
static int real_new_index_call_fixed(std::true_type, lua_State* L) {
|
||||||
auto& src = get_src(L);
|
auto& src = get_src(L);
|
||||||
#ifdef SOL_CHECK_ARGUMENTS
|
#ifdef SOL_CHECK_ARGUMENTS
|
||||||
auto maybek = stack::check_get<K>(L, 2);
|
auto maybek = stack::check_get<K>(L, 2);
|
||||||
if (!maybek) {
|
if (!maybek) {
|
||||||
return luaL_error(L, "sol: improper key of type %s to a %s", lua_typename(L, static_cast<int>(type_of(L, 2))), detail::demangle<T>().c_str());
|
return luaL_error(L, "sol: improper key of type %s for %s", lua_typename(L, static_cast<int>(type_of(L, 2))), detail::demangle<T>().c_str());
|
||||||
}
|
}
|
||||||
K& k = *maybek;
|
K& k = *maybek;
|
||||||
#else
|
#else
|
||||||
|
@ -12658,6 +12683,33 @@ namespace sol {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int real_new_index_call_fixed(std::false_type, lua_State* L) {
|
||||||
|
auto& src = get_src(L);
|
||||||
|
#ifdef SOL_CHECK_ARGUMENTS
|
||||||
|
auto maybek = stack::check_get<K>(L, 2);
|
||||||
|
if (!maybek) {
|
||||||
|
return luaL_error(L, "sol: improper key of type %s for %s", lua_typename(L, static_cast<int>(type_of(L, 2))), detail::demangle<T>().c_str());
|
||||||
|
}
|
||||||
|
K& k = *maybek;
|
||||||
|
#else
|
||||||
|
K k = stack::get<K>(L, 2);
|
||||||
|
#endif
|
||||||
|
using std::end;
|
||||||
|
auto it = detail::find(src, k);
|
||||||
|
if (it != end(src)) {
|
||||||
|
auto& v = *it;
|
||||||
|
v.second = stack::get<V>(L, 3);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return luaL_error(L, "sol: cannot insert key of type %s to into %s", lua_typename(L, static_cast<int>(type_of(L, 2))), detail::demangle<T>().c_str());
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int real_new_index_call_const(std::true_type, std::true_type, lua_State* L) {
|
||||||
|
return real_new_index_call_fixed(std::integral_constant<bool, detail::has_insert<T>::value>(), L);
|
||||||
|
}
|
||||||
|
|
||||||
static int real_new_index_call_const(std::true_type, std::false_type, lua_State* L) {
|
static int real_new_index_call_const(std::true_type, std::false_type, lua_State* L) {
|
||||||
auto& src = get_src(L);
|
auto& src = get_src(L);
|
||||||
#ifdef SOL_CHECK_ARGUMENTS
|
#ifdef SOL_CHECK_ARGUMENTS
|
||||||
|
@ -12692,7 +12744,7 @@ namespace sol {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int real_new_index_call(lua_State* L) {
|
static int real_new_index_call(lua_State* L) {
|
||||||
return real_new_index_call_const(meta::neg<meta::any<std::is_const<V>, std::is_const<IR>, meta::neg<std::is_copy_assignable<V>>>>(), is_associative(), L);
|
return real_new_index_call_const(meta::neg<meta::any<std::is_const<V>, std::is_const<IR>, meta::neg<std::is_copy_assignable<V>>>>(), meta::all<is_associative, detail::has_insert<T>>(), L);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int real_pairs_next_call_assoc(std::true_type, lua_State* L) {
|
static int real_pairs_next_call_assoc(std::true_type, lua_State* L) {
|
||||||
|
@ -12896,6 +12948,10 @@ namespace sol {
|
||||||
return detail::typed_static_trampoline<decltype(&real_pairs_call), (&real_pairs_call)>(L);
|
return detail::typed_static_trampoline<decltype(&real_pairs_call), (&real_pairs_call)>(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_call(lua_State*L) {
|
||||||
|
return detail::typed_static_trampoline<decltype(&real_get_call), (&real_get_call)>(L);
|
||||||
|
}
|
||||||
|
|
||||||
static int index_call(lua_State*L) {
|
static int index_call(lua_State*L) {
|
||||||
return detail::typed_static_trampoline<decltype(&real_index_call), (&real_index_call)>(L);
|
return detail::typed_static_trampoline<decltype(&real_index_call), (&real_index_call)>(L);
|
||||||
}
|
}
|
||||||
|
@ -12910,12 +12966,13 @@ namespace sol {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline auto container_metatable() {
|
inline auto container_metatable() {
|
||||||
typedef container_usertype_metatable<std::remove_pointer_t<T>> meta_cumt;
|
typedef container_usertype_metatable<std::remove_pointer_t<T>> meta_cumt;
|
||||||
std::array<luaL_Reg, 11> reg = { {
|
std::array<luaL_Reg, 12> reg = { {
|
||||||
{ "__index", &meta_cumt::index_call },
|
{ "__index", &meta_cumt::index_call },
|
||||||
{ "__newindex", &meta_cumt::new_index_call },
|
{ "__newindex", &meta_cumt::new_index_call },
|
||||||
{ "__pairs", &meta_cumt::pairs_call },
|
{ "__pairs", &meta_cumt::pairs_call },
|
||||||
{ "__ipairs", &meta_cumt::pairs_call },
|
{ "__ipairs", &meta_cumt::pairs_call },
|
||||||
{ "__len", &meta_cumt::length_call },
|
{ "__len", &meta_cumt::length_call },
|
||||||
|
{ "get", &meta_cumt::get_call },
|
||||||
{ "clear", &meta_cumt::clear_call },
|
{ "clear", &meta_cumt::clear_call },
|
||||||
{ "insert", &meta_cumt::insert_call },
|
{ "insert", &meta_cumt::insert_call },
|
||||||
{ "add", &meta_cumt::add_call },
|
{ "add", &meta_cumt::add_call },
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#define SOL_CONTAINER_USERTYPE_HPP
|
#define SOL_CONTAINER_USERTYPE_HPP
|
||||||
|
|
||||||
#include "stack.hpp"
|
#include "stack.hpp"
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace sol {
|
namespace sol {
|
||||||
|
|
||||||
|
@ -108,7 +109,7 @@ namespace sol {
|
||||||
|
|
||||||
template <typename Raw, typename C = void>
|
template <typename Raw, typename C = void>
|
||||||
struct container_usertype_metatable {
|
struct container_usertype_metatable {
|
||||||
typedef meta::has_key_value_pair<meta::unqualified_t<Raw>> is_associative;
|
typedef meta::is_associative<std::remove_pointer_t<meta::unqualified_t<Raw>>> is_associative;
|
||||||
typedef meta::unqualified_t<Raw> T;
|
typedef meta::unqualified_t<Raw> T;
|
||||||
typedef typename T::iterator I;
|
typedef typename T::iterator I;
|
||||||
typedef std::conditional_t<is_associative::value, typename T::value_type, std::pair<std::size_t, typename T::value_type>> KV;
|
typedef std::conditional_t<is_associative::value, typename T::value_type, std::pair<std::size_t, typename T::value_type>> KV;
|
||||||
|
@ -143,6 +144,25 @@ namespace sol {
|
||||||
#endif // Safe getting with error
|
#endif // Safe getting with error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int delegate_call(lua_State* L) {
|
||||||
|
static std::unordered_map<std::string, lua_CFunction> calls{
|
||||||
|
{ "add", &real_add_call },
|
||||||
|
{ "insert", &real_insert_call },
|
||||||
|
{ "clear", &real_clear_call },
|
||||||
|
{ "find", &real_find_call },
|
||||||
|
{ "get", &real_get_call }
|
||||||
|
};
|
||||||
|
auto maybename = stack::check_get<std::string>(L, 2);
|
||||||
|
if (maybename) {
|
||||||
|
auto& name = *maybename;
|
||||||
|
auto it = calls.find(name);
|
||||||
|
if (it != calls.cend()) {
|
||||||
|
return stack::push(L, it->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stack::push(L, lua_nil);
|
||||||
|
}
|
||||||
|
|
||||||
static int real_index_call_associative(std::true_type, lua_State* L) {
|
static int real_index_call_associative(std::true_type, lua_State* L) {
|
||||||
auto k = stack::check_get<K>(L, 2);
|
auto k = stack::check_get<K>(L, 2);
|
||||||
if (k) {
|
if (k) {
|
||||||
|
@ -155,22 +175,7 @@ namespace sol {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto maybename = stack::check_get<string_detail::string_shim>(L, 2);
|
return delegate_call(L);
|
||||||
if (maybename) {
|
|
||||||
auto& name = *maybename;
|
|
||||||
if (name == "add") {
|
|
||||||
return stack::push(L, &add_call);
|
|
||||||
}
|
|
||||||
else if (name == "insert") {
|
|
||||||
return stack::push(L, &insert_call);
|
|
||||||
}
|
|
||||||
else if (name == "clear") {
|
|
||||||
return stack::push(L, &clear_call);
|
|
||||||
}
|
|
||||||
else if (name == "find") {
|
|
||||||
return stack::push(L, &find_call);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return stack::push(L, lua_nil);
|
return stack::push(L, lua_nil);
|
||||||
}
|
}
|
||||||
|
@ -190,22 +195,7 @@ namespace sol {
|
||||||
return stack::stack_detail::push_reference<push_type>(L, *it);
|
return stack::stack_detail::push_reference<push_type>(L, *it);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto maybename = stack::check_get<string_detail::string_shim>(L, 2);
|
return delegate_call(L);
|
||||||
if (maybename) {
|
|
||||||
auto& name = *maybename;
|
|
||||||
if (name == "add") {
|
|
||||||
return stack::push(L, &add_call);
|
|
||||||
}
|
|
||||||
else if (name == "insert") {
|
|
||||||
return stack::push(L, &insert_call);
|
|
||||||
}
|
|
||||||
else if (name == "clear") {
|
|
||||||
return stack::push(L, &clear_call);
|
|
||||||
}
|
|
||||||
else if (name == "find") {
|
|
||||||
return stack::push(L, &find_call);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return stack::push(L, lua_nil);
|
return stack::push(L, lua_nil);
|
||||||
|
@ -215,6 +205,10 @@ namespace sol {
|
||||||
return real_index_call_associative(is_associative(), L);
|
return real_index_call_associative(is_associative(), L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int real_get_call(lua_State* L) {
|
||||||
|
return real_index_call_associative(is_associative(), L);
|
||||||
|
}
|
||||||
|
|
||||||
static int real_new_index_call_const(std::false_type, std::false_type, lua_State* L) {
|
static int real_new_index_call_const(std::false_type, std::false_type, lua_State* L) {
|
||||||
return luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)");
|
return luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)");
|
||||||
}
|
}
|
||||||
|
@ -223,12 +217,12 @@ namespace sol {
|
||||||
return luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)");
|
return luaL_error(L, "sol: cannot write to a const value type or an immutable iterator (e.g., std::set)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int real_new_index_call_const(std::true_type, std::true_type, lua_State* L) {
|
static int real_new_index_call_fixed(std::true_type, lua_State* L) {
|
||||||
auto& src = get_src(L);
|
auto& src = get_src(L);
|
||||||
#ifdef SOL_CHECK_ARGUMENTS
|
#ifdef SOL_CHECK_ARGUMENTS
|
||||||
auto maybek = stack::check_get<K>(L, 2);
|
auto maybek = stack::check_get<K>(L, 2);
|
||||||
if (!maybek) {
|
if (!maybek) {
|
||||||
return luaL_error(L, "sol: improper key of type %s to a %s", lua_typename(L, static_cast<int>(type_of(L, 2))), detail::demangle<T>().c_str());
|
return luaL_error(L, "sol: improper key of type %s for %s", lua_typename(L, static_cast<int>(type_of(L, 2))), detail::demangle<T>().c_str());
|
||||||
}
|
}
|
||||||
K& k = *maybek;
|
K& k = *maybek;
|
||||||
#else
|
#else
|
||||||
|
@ -246,6 +240,33 @@ namespace sol {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int real_new_index_call_fixed(std::false_type, lua_State* L) {
|
||||||
|
auto& src = get_src(L);
|
||||||
|
#ifdef SOL_CHECK_ARGUMENTS
|
||||||
|
auto maybek = stack::check_get<K>(L, 2);
|
||||||
|
if (!maybek) {
|
||||||
|
return luaL_error(L, "sol: improper key of type %s for %s", lua_typename(L, static_cast<int>(type_of(L, 2))), detail::demangle<T>().c_str());
|
||||||
|
}
|
||||||
|
K& k = *maybek;
|
||||||
|
#else
|
||||||
|
K k = stack::get<K>(L, 2);
|
||||||
|
#endif
|
||||||
|
using std::end;
|
||||||
|
auto it = detail::find(src, k);
|
||||||
|
if (it != end(src)) {
|
||||||
|
auto& v = *it;
|
||||||
|
v.second = stack::get<V>(L, 3);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return luaL_error(L, "sol: cannot insert key of type %s to into %s", lua_typename(L, static_cast<int>(type_of(L, 2))), detail::demangle<T>().c_str());
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int real_new_index_call_const(std::true_type, std::true_type, lua_State* L) {
|
||||||
|
return real_new_index_call_fixed(std::integral_constant<bool, detail::has_insert<T>::value>(), L);
|
||||||
|
}
|
||||||
|
|
||||||
static int real_new_index_call_const(std::true_type, std::false_type, lua_State* L) {
|
static int real_new_index_call_const(std::true_type, std::false_type, lua_State* L) {
|
||||||
auto& src = get_src(L);
|
auto& src = get_src(L);
|
||||||
#ifdef SOL_CHECK_ARGUMENTS
|
#ifdef SOL_CHECK_ARGUMENTS
|
||||||
|
@ -280,7 +301,7 @@ namespace sol {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int real_new_index_call(lua_State* L) {
|
static int real_new_index_call(lua_State* L) {
|
||||||
return real_new_index_call_const(meta::neg<meta::any<std::is_const<V>, std::is_const<IR>, meta::neg<std::is_copy_assignable<V>>>>(), is_associative(), L);
|
return real_new_index_call_const(meta::neg<meta::any<std::is_const<V>, std::is_const<IR>, meta::neg<std::is_copy_assignable<V>>>>(), meta::all<is_associative, detail::has_insert<T>>(), L);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int real_pairs_next_call_assoc(std::true_type, lua_State* L) {
|
static int real_pairs_next_call_assoc(std::true_type, lua_State* L) {
|
||||||
|
@ -484,6 +505,10 @@ namespace sol {
|
||||||
return detail::typed_static_trampoline<decltype(&real_pairs_call), (&real_pairs_call)>(L);
|
return detail::typed_static_trampoline<decltype(&real_pairs_call), (&real_pairs_call)>(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_call(lua_State*L) {
|
||||||
|
return detail::typed_static_trampoline<decltype(&real_get_call), (&real_get_call)>(L);
|
||||||
|
}
|
||||||
|
|
||||||
static int index_call(lua_State*L) {
|
static int index_call(lua_State*L) {
|
||||||
return detail::typed_static_trampoline<decltype(&real_index_call), (&real_index_call)>(L);
|
return detail::typed_static_trampoline<decltype(&real_index_call), (&real_index_call)>(L);
|
||||||
}
|
}
|
||||||
|
@ -498,12 +523,13 @@ namespace sol {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline auto container_metatable() {
|
inline auto container_metatable() {
|
||||||
typedef container_usertype_metatable<std::remove_pointer_t<T>> meta_cumt;
|
typedef container_usertype_metatable<std::remove_pointer_t<T>> meta_cumt;
|
||||||
std::array<luaL_Reg, 11> reg = { {
|
std::array<luaL_Reg, 12> reg = { {
|
||||||
{ "__index", &meta_cumt::index_call },
|
{ "__index", &meta_cumt::index_call },
|
||||||
{ "__newindex", &meta_cumt::new_index_call },
|
{ "__newindex", &meta_cumt::new_index_call },
|
||||||
{ "__pairs", &meta_cumt::pairs_call },
|
{ "__pairs", &meta_cumt::pairs_call },
|
||||||
{ "__ipairs", &meta_cumt::pairs_call },
|
{ "__ipairs", &meta_cumt::pairs_call },
|
||||||
{ "__len", &meta_cumt::length_call },
|
{ "__len", &meta_cumt::length_call },
|
||||||
|
{ "get", &meta_cumt::get_call },
|
||||||
{ "clear", &meta_cumt::clear_call },
|
{ "clear", &meta_cumt::clear_call },
|
||||||
{ "insert", &meta_cumt::insert_call },
|
{ "insert", &meta_cumt::insert_call },
|
||||||
{ "add", &meta_cumt::add_call },
|
{ "add", &meta_cumt::add_call },
|
||||||
|
|
|
@ -276,6 +276,24 @@ namespace sol {
|
||||||
static std::false_type test(...);
|
static std::false_type test(...);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct has_key_type_impl {
|
||||||
|
template<typename T, typename U = unqualified_t<T>,
|
||||||
|
typename V = typename U::key_type>
|
||||||
|
static std::true_type test(int);
|
||||||
|
|
||||||
|
template<typename...>
|
||||||
|
static std::false_type test(...);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct has_mapped_type_impl {
|
||||||
|
template<typename T, typename U = unqualified_t<T>,
|
||||||
|
typename V = typename U::mapped_type>
|
||||||
|
static std::true_type test(int);
|
||||||
|
|
||||||
|
template<typename...>
|
||||||
|
static std::false_type test(...);
|
||||||
|
};
|
||||||
|
|
||||||
struct has_key_value_pair_impl {
|
struct has_key_value_pair_impl {
|
||||||
template<typename T, typename U = unqualified_t<T>,
|
template<typename T, typename U = unqualified_t<T>,
|
||||||
typename V = typename U::value_type,
|
typename V = typename U::value_type,
|
||||||
|
@ -315,6 +333,15 @@ namespace sol {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test<T>(0)) {};
|
struct has_key_value_pair : decltype(meta_detail::has_key_value_pair_impl::test<T>(0)) {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct has_key_type : decltype(meta_detail::has_key_type_impl::test<T>(0)) {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct has_mapped_type : decltype(meta_detail::has_mapped_type_impl::test<T>(0)) {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_associative : meta::all<has_key_value_pair<T>, has_mapped_type<T>> {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using is_string_constructible = any<std::is_same<unqualified_t<T>, const char*>, std::is_same<unqualified_t<T>, char>, std::is_same<unqualified_t<T>, std::string>, std::is_same<unqualified_t<T>, std::initializer_list<char>>>;
|
using is_string_constructible = any<std::is_same<unqualified_t<T>, const char*>, std::is_same<unqualified_t<T>, char>, std::is_same<unqualified_t<T>, std::string>, std::is_same<unqualified_t<T>, std::initializer_list<char>>>;
|
||||||
|
|
||||||
|
|
|
@ -399,6 +399,11 @@ namespace sol {
|
||||||
return as_table_t<T>(std::forward<T>(container));
|
return as_table_t<T>(std::forward<T>(container));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
nested<T> as_nested(T&& container) {
|
||||||
|
return as_nested<T>(std::forward<T>(container));
|
||||||
|
}
|
||||||
|
|
||||||
struct this_state {
|
struct this_state {
|
||||||
lua_State* L;
|
lua_State* L;
|
||||||
operator lua_State* () const {
|
operator lua_State* () const {
|
||||||
|
|
|
@ -11,16 +11,20 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
std::vector<int> test_table_return_one() {
|
auto test_table_return_one() {
|
||||||
return{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
|
return sol::as_table(std::vector<int>{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 });
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<std::string, int>> test_table_return_two() {
|
auto test_table_return_two() {
|
||||||
return{ { "one", 1 },{ "two", 2 },{ "three", 3 } };
|
return sol::as_table(std::vector<std::pair<std::string, int>>{ { "one", 1 },{ "two", 2 },{ "three", 3 } });
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, std::string> test_table_return_three() {
|
auto test_table_return_three() {
|
||||||
return{ { "name", "Rapptz" },{ "friend", "ThePhD" },{ "project", "sol" } };
|
return sol::as_table(std::map<std::string, std::string>{ { "name", "Rapptz" },{ "friend", "ThePhD" },{ "project", "sol" } });
|
||||||
|
}
|
||||||
|
|
||||||
|
auto test_table_return_four() {
|
||||||
|
return sol::as_table(std::array<std::pair<std::string, int>, 4>{ { { "one", 1 },{ "two", 2 },{ "three", 3 },{ "four", 4 } } });
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("containers/returns", "make sure that even references to vectors are being serialized as tables") {
|
TEST_CASE("containers/returns", "make sure that even references to vectors are being serialized as tables") {
|
||||||
|
@ -249,10 +253,12 @@ TEST_CASE("containers/arbitrary-creation", "userdata and tables should be usable
|
||||||
lua.set_function("test_one", test_table_return_one);
|
lua.set_function("test_one", test_table_return_one);
|
||||||
lua.set_function("test_two", test_table_return_two);
|
lua.set_function("test_two", test_table_return_two);
|
||||||
lua.set_function("test_three", test_table_return_three);
|
lua.set_function("test_three", test_table_return_three);
|
||||||
|
lua.set_function("test_four", test_table_return_four);
|
||||||
|
|
||||||
REQUIRE_NOTHROW(lua.script("a = test_one()"));
|
REQUIRE_NOTHROW(lua.script("a = test_one()"));
|
||||||
REQUIRE_NOTHROW(lua.script("b = test_two()"));
|
REQUIRE_NOTHROW(lua.script("b = test_two()"));
|
||||||
REQUIRE_NOTHROW(lua.script("c = test_three()"));
|
REQUIRE_NOTHROW(lua.script("c = test_three()"));
|
||||||
|
REQUIRE_NOTHROW(lua.script("d = test_four()"));
|
||||||
|
|
||||||
REQUIRE_NOTHROW(lua.script("assert(#a == 10, 'error')"));
|
REQUIRE_NOTHROW(lua.script("assert(#a == 10, 'error')"));
|
||||||
REQUIRE_NOTHROW(lua.script("assert(a[3] == 3, 'error')"));
|
REQUIRE_NOTHROW(lua.script("assert(a[3] == 3, 'error')"));
|
||||||
|
@ -260,10 +266,14 @@ TEST_CASE("containers/arbitrary-creation", "userdata and tables should be usable
|
||||||
REQUIRE_NOTHROW(lua.script("assert(b.three == 3, 'error')"));
|
REQUIRE_NOTHROW(lua.script("assert(b.three == 3, 'error')"));
|
||||||
REQUIRE_NOTHROW(lua.script("assert(c.name == 'Rapptz', 'error')"));
|
REQUIRE_NOTHROW(lua.script("assert(c.name == 'Rapptz', 'error')"));
|
||||||
REQUIRE_NOTHROW(lua.script("assert(c.project == 'sol', 'error')"));
|
REQUIRE_NOTHROW(lua.script("assert(c.project == 'sol', 'error')"));
|
||||||
|
REQUIRE_NOTHROW(lua.script("assert(d.one == 1, 'error')"));
|
||||||
|
REQUIRE_NOTHROW(lua.script("assert(d.three == 3, 'error')"));
|
||||||
|
REQUIRE_NOTHROW(lua.script("assert(d.four == 4, 'error')"));
|
||||||
|
|
||||||
sol::table a = lua.get<sol::table>("a");
|
sol::table a = lua.get<sol::table>("a");
|
||||||
sol::table b = lua.get<sol::table>("b");
|
sol::table b = lua.get<sol::table>("b");
|
||||||
sol::table c = lua.get<sol::table>("c");
|
sol::table c = lua.get<sol::table>("c");
|
||||||
|
sol::table d = lua["d"];
|
||||||
|
|
||||||
REQUIRE(a.size() == 10ULL);
|
REQUIRE(a.size() == 10ULL);
|
||||||
REQUIRE(a.get<int>(3) == 3);
|
REQUIRE(a.get<int>(3) == 3);
|
||||||
|
@ -271,6 +281,9 @@ TEST_CASE("containers/arbitrary-creation", "userdata and tables should be usable
|
||||||
REQUIRE(b.get<int>("three") == 3);
|
REQUIRE(b.get<int>("three") == 3);
|
||||||
REQUIRE(c.get<std::string>("name") == "Rapptz");
|
REQUIRE(c.get<std::string>("name") == "Rapptz");
|
||||||
REQUIRE(c.get<std::string>("project") == "sol");
|
REQUIRE(c.get<std::string>("project") == "sol");
|
||||||
|
REQUIRE(d.get<int>("one") == 1);
|
||||||
|
REQUIRE(d.get<int>("three") == 3);
|
||||||
|
REQUIRE(d.get<int>("four") == 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("containers/extra-functions", "make sure the manipulation functions are present and usable and working across various container types") {
|
TEST_CASE("containers/extra-functions", "make sure the manipulation functions are present and usable and working across various container types") {
|
||||||
|
@ -540,7 +553,7 @@ TEST_CASE("containers/to_args", "Test that the to_args abstractions works") {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("containers/ipairs-test", "ensure that abstractions roundtrip properly and push nils to stop pairs / ipairs") {
|
TEST_CASE("containers/ipairs-test", "ensure that abstractions roundtrip properly") {
|
||||||
struct thing {
|
struct thing {
|
||||||
int x = 20;
|
int x = 20;
|
||||||
};
|
};
|
||||||
|
@ -752,3 +765,59 @@ end
|
||||||
)lua");
|
)lua");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("containers/pairs", "test how well pairs work with the underlying system") {
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
lua.open_libraries(sol::lib::base);
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, int>> a{ { "one", 1 },{ "two", 2 },{ "three", 3 },{ "four", 4 },{ "five", 5 } };
|
||||||
|
std::array<std::pair<std::string, int>, 5> b{ { { "one", 1 },{ "two", 2 },{ "three", 3 },{ "four", 4 },{ "five", 5 } } };
|
||||||
|
//std::pair<std::string, int> c[5]{ { "one", 1 },{ "two", 2 },{ "three", 3 },{ "four", 4 },{ "five", 5 } };
|
||||||
|
//int d[5] = { 1, 2, 3, 4, 5 };
|
||||||
|
|
||||||
|
lua["a"] = std::ref(a);
|
||||||
|
lua["b"] = &b;
|
||||||
|
//lua["c"] = std::ref(c);
|
||||||
|
//lua["d"] = &d;
|
||||||
|
|
||||||
|
lua.script("av1, av2 = a:get(1)");
|
||||||
|
lua.script("bv1, bv2 = b:get(1)");
|
||||||
|
//lua.script("cv1, cv2 = c:get(1)");
|
||||||
|
//lua.script("dv1, dv2 = d:get(1)");
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, int>>& la = lua["a"];
|
||||||
|
std::array<std::pair<std::string, int>, 5>& lb = lua["b"];
|
||||||
|
//std::pair<std::string, int> (&lc)[5] = lua["c"];
|
||||||
|
//int (&lc)[5] = lua["d"];
|
||||||
|
|
||||||
|
std::pair<std::string, int>& va = la[0];
|
||||||
|
std::pair<std::string, int>& vb = lb[0];
|
||||||
|
//std::pair<std::string, int>& vc = lc[0];
|
||||||
|
//int vd = ld[0];
|
||||||
|
std::string av1 = lua["av1"];
|
||||||
|
int av2 = lua["av2"];
|
||||||
|
std::string bv1 = lua["bv1"];
|
||||||
|
int bv2 = lua["bv2"];
|
||||||
|
//std::string cv1 = lua["cv1"];
|
||||||
|
//int cv2 = lua["cv2"];
|
||||||
|
//int dv1 = lua["dv1"];
|
||||||
|
//sol::lua_nil_t dv2 = lua["dv2"];
|
||||||
|
|
||||||
|
REQUIRE(va.first == "one");
|
||||||
|
REQUIRE(va.second == 1);
|
||||||
|
REQUIRE(vb.first == "one");
|
||||||
|
REQUIRE(vb.second == 1);
|
||||||
|
//REQUIRE(vc.first == "one");
|
||||||
|
//REQUIRE(vc.second == 1);
|
||||||
|
//REQUIRE(vd == 1);
|
||||||
|
|
||||||
|
REQUIRE(av1 == "one");
|
||||||
|
REQUIRE(av2 == 1);
|
||||||
|
REQUIRE(bv1 == "one");
|
||||||
|
REQUIRE(bv2 == 1);
|
||||||
|
//REQUIRE(cv1 == "one");
|
||||||
|
//REQUIRE(cv2 == 1);
|
||||||
|
//REQUIRE(dv1 == 1);
|
||||||
|
//REQUIRE(dv2 == sol::lua_nil);
|
||||||
|
}
|
||||||
|
|
|
@ -671,17 +671,17 @@ TEST_CASE("usertype/private-constructible", "Check to make sure special snowflak
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("usertype/const-pointer", "Make sure const pointers can be taken") {
|
TEST_CASE("usertype/const-pointer", "Make sure const pointers can be taken") {
|
||||||
struct A { int x = 201; };
|
struct A_x { int x = 201; };
|
||||||
struct B {
|
struct B_foo {
|
||||||
int foo(const A* a) { return a->x; };
|
int foo(const A_x* a) { return a->x; };
|
||||||
};
|
};
|
||||||
|
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
lua.new_usertype<B>("B",
|
lua.new_usertype<B_foo>("B",
|
||||||
"foo", &B::foo
|
"foo", &B_foo::foo
|
||||||
);
|
);
|
||||||
lua.set("a", A());
|
lua.set("a", A_x());
|
||||||
lua.set("b", B());
|
lua.set("b", B_foo());
|
||||||
lua.script("x = b:foo(a)");
|
lua.script("x = b:foo(a)");
|
||||||
int x = lua["x"];
|
int x = lua["x"];
|
||||||
REQUIRE(x == 201);
|
REQUIRE(x == 201);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user