diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 61aa942b..d2e577f3 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -59,7 +59,8 @@ function (MAKE_EXAMPLE example_source_file example_suffix target_sol example_tes add_executable(${example_name} ${example_source_file} source/assert.hpp) set_target_properties(${example_name} PROPERTIES - OUTPUT_NAME "${example_output_name}") + OUTPUT_NAME "${example_output_name}" + EXPORT_NAME sol2::${example_output_name}) target_link_libraries(${example_name} ${target_sol}) target_compile_features(${example_name} PRIVATE ${CXX_FEATURES}) @@ -90,13 +91,13 @@ if (SOL2_EXAMPLES) endforeach() endif() -if (SOL2_SINGLE AND SOL2_EXAMPLES_SINGLE) +if (SOL2_EXAMPLES_SINGLE) foreach(example_source_file ${EXAMPLES_SRC}) MAKE_EXAMPLE(${example_source_file} ".single" sol2::sol2_single SOL2_TESTS_EXAMPLES) endforeach() endif() -if (SOL2_GENERATE_SINGLE AND SOL2_EXAMPLES_SINGLE_GENERATED) +if (SOL2_EXAMPLES_SINGLE_GENERATED) foreach(example_source_file ${EXAMPLES_SRC}) MAKE_EXAMPLE(${example_source_file} ".single.generated" sol2::sol2_single_generated SOL2_TESTS_EXAMPLES) endforeach() diff --git a/include/sol/bind_traits.hpp b/include/sol/bind_traits.hpp index 3a5a56fb..14095536 100644 --- a/include/sol/bind_traits.hpp +++ b/include/sol/bind_traits.hpp @@ -24,7 +24,7 @@ #ifndef SOL_BIND_TRAITS_HPP #define SOL_BIND_TRAITS_HPP -#include "feature_test.hpp" +#include "forward.hpp" #include "tuple.hpp" namespace sol { diff --git a/include/sol/container_traits.hpp b/include/sol/container_traits.hpp index 3e2af1a3..5a44b235 100644 --- a/include/sol/container_traits.hpp +++ b/include/sol/container_traits.hpp @@ -27,6 +27,7 @@ #include "traits.hpp" #include "stack.hpp" #include "map.hpp" +#include "object.hpp" namespace sol { diff --git a/include/sol/function_types_core.hpp b/include/sol/function_types_core.hpp index f255308a..5a86960b 100644 --- a/include/sol/function_types_core.hpp +++ b/include/sol/function_types_core.hpp @@ -26,6 +26,7 @@ #include "stack.hpp" #include "wrapper.hpp" + #include namespace sol { diff --git a/include/sol/function_types_stateful.hpp b/include/sol/function_types_stateful.hpp index 4943ca77..20153c02 100644 --- a/include/sol/function_types_stateful.hpp +++ b/include/sol/function_types_stateful.hpp @@ -25,6 +25,7 @@ #define SOL_FUNCTION_TYPES_STATEFUL_HPP #include "function_types_core.hpp" +#include "call.hpp" namespace sol { namespace function_detail { diff --git a/include/sol/function_types_stateless.hpp b/include/sol/function_types_stateless.hpp index 8b996e28..2be15860 100644 --- a/include/sol/function_types_stateless.hpp +++ b/include/sol/function_types_stateless.hpp @@ -25,6 +25,7 @@ #define SOL_FUNCTION_TYPES_STATELESS_HPP #include "stack.hpp" +#include "call.hpp" namespace sol { namespace function_detail { diff --git a/include/sol/metatable.hpp b/include/sol/metatable.hpp index 93b818ff..8e2e598e 100644 --- a/include/sol/metatable.hpp +++ b/include/sol/metatable.hpp @@ -25,7 +25,7 @@ #define SOL_METATABLE_HPP #include "table_core.hpp" -#include "usertype_core.hpp" +#include "usertype.hpp" namespace sol { diff --git a/include/sol/raii.hpp b/include/sol/raii.hpp index 0f84b08d..da267573 100644 --- a/include/sol/raii.hpp +++ b/include/sol/raii.hpp @@ -25,6 +25,7 @@ #define SOL_RAII_HPP #include "traits.hpp" +#include "compatibility.hpp" #include diff --git a/include/sol/sol.hpp b/include/sol/sol.hpp index b7523877..a7b3d10f 100644 --- a/include/sol/sol.hpp +++ b/include/sol/sol.hpp @@ -57,7 +57,9 @@ #include "protected_function.hpp" #include "state.hpp" #include "coroutine.hpp" +#include "thread.hpp" #include "userdata.hpp" +#include "metatable.hpp" #include "variadic_args.hpp" #include "variadic_results.hpp" diff --git a/include/sol/stack_push.hpp b/include/sol/stack_push.hpp index f57ec822..d546504b 100644 --- a/include/sol/stack_push.hpp +++ b/include/sol/stack_push.hpp @@ -35,6 +35,7 @@ #include #include #include +#include #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES #include #include diff --git a/include/sol/table_core.hpp b/include/sol/table_core.hpp index ffd779e6..4bd94981 100644 --- a/include/sol/table_core.hpp +++ b/include/sol/table_core.hpp @@ -30,6 +30,7 @@ #include "table_iterator.hpp" #include "types.hpp" #include "object_base.hpp" +#include "usertype.hpp" namespace sol { namespace detail { diff --git a/include/sol/thread.hpp b/include/sol/thread.hpp index 6bcc403a..78176077 100644 --- a/include/sol/thread.hpp +++ b/include/sol/thread.hpp @@ -26,6 +26,7 @@ #include "reference.hpp" #include "stack.hpp" +#include "state_view.hpp" namespace sol { struct lua_thread_state { diff --git a/include/sol/tuple.hpp b/include/sol/tuple.hpp index e6c599e4..3775176c 100644 --- a/include/sol/tuple.hpp +++ b/include/sol/tuple.hpp @@ -24,6 +24,8 @@ #ifndef SOL_TUPLE_HPP #define SOL_TUPLE_HPP +#include "forward.hpp" + #include #include diff --git a/include/sol/usertype_core.hpp b/include/sol/usertype_core.hpp index 1a8481c1..649c8407 100644 --- a/include/sol/usertype_core.hpp +++ b/include/sol/usertype_core.hpp @@ -33,6 +33,7 @@ #include "raii.hpp" #include "deprecate.hpp" #include "object.hpp" +#include "function_types.hpp" #include #include diff --git a/include/sol/usertype_storage.hpp b/include/sol/usertype_storage.hpp index 2ffdd3cb..3b65c152 100644 --- a/include/sol/usertype_storage.hpp +++ b/include/sol/usertype_storage.hpp @@ -579,10 +579,9 @@ namespace sol { namespace u_detail { void* derived_this = static_cast(static_cast*>(this)); index_call_storage ics; ics.binding_data = b.data(); - //ics.index = is_index ? static_cast(&Binding::call_with_) - // : static_cast(&Binding::index_call_with_); - //ics.new_index = is_new_index ? static_cast(&Binding::call_with_) - // : static_cast(&Binding::index_call_with_); + ics.index = is_index ? &Binding::template call_with_ : &Binding::template index_call_with_; + ics.new_index = is_new_index ? &Binding::template call_with_ + : &Binding::template index_call_with_; // need to swap everything to use fast indexing here auto for_each_backing_metatable = [&](lua_State* L, submetatable_type smt, reference& fast_index_table) { if (smt == submetatable_type::named) { @@ -691,7 +690,7 @@ namespace sol { namespace u_detail { // we create a metatable to attach to the regular gc_table // so that the destructor is called for the usertype storage int usertype_storage_metatabe_count = stack::push(L, new_table(0, 1)); - stack_table usertype_storage_metatable(L, -usertype_storage_metatabe_count); + stack_reference usertype_storage_metatable(L, -usertype_storage_metatabe_count); // set the destruction routine on the metatable stack::set_field(L, meta_function::garbage_collect, detail::user_alloc_destruct>, usertype_storage_metatable.stack_index()); // set the metatable on the usertype storage userdata diff --git a/single/include/sol/forward.hpp b/single/include/sol/forward.hpp index 14580f30..42fa0432 100644 --- a/single/include/sol/forward.hpp +++ b/single/include/sol/forward.hpp @@ -20,7 +20,7 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2018-12-19 15:47:44.640280 UTC +// Generated 2018-12-19 18:01:44.554823 UTC // This header was generated with sol v2.20.6 (revision 9b29277) // https://github.com/ThePhD/sol2 diff --git a/single/include/sol/sol.hpp b/single/include/sol/sol.hpp index a573d9e2..64a3a963 100644 --- a/single/include/sol/sol.hpp +++ b/single/include/sol/sol.hpp @@ -20,7 +20,7 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // This file was generated with a script. -// Generated 2018-12-19 15:47:44.363023 UTC +// Generated 2018-12-19 18:01:43.480660 UTC // This header was generated with sol v2.20.6 (revision 9b29277) // https://github.com/ThePhD/sol2 @@ -16990,503 +16990,6 @@ namespace sol { // end of sol/table_iterator.hpp -namespace sol { - namespace detail { - template - struct clean { - lua_State* L; - clean(lua_State* luastate) : L(luastate) { - } - ~clean() { - lua_pop(L, static_cast(n)); - } - }; - struct ref_clean { - lua_State* L; - int& n; - ref_clean(lua_State* luastate, int& n) : L(luastate), n(n) { - } - ~ref_clean() { - lua_pop(L, static_cast(n)); - } - }; - inline int fail_on_newindex(lua_State* L) { - return luaL_error(L, "sol: cannot modify the elements of an enumeration table"); - } - } // namespace detail - - template - class basic_table_core : public basic_object_base { - typedef basic_object_base base_t; - friend class state; - friend class state_view; - - template - using is_global = meta::all, meta::is_c_str...>; - - template - void for_each(std::true_type, Fx&& fx) const { - auto pp = stack::push_pop(*this); - stack::push(base_t::lua_state(), lua_nil); - while (lua_next(base_t::lua_state(), -2)) { - object key(base_t::lua_state(), -2); - object value(base_t::lua_state(), -1); - std::pair keyvalue(key, value); - auto pn = stack::pop_n(base_t::lua_state(), 1); - fx(keyvalue); - } - } - - template - void for_each(std::false_type, Fx&& fx) const { - auto pp = stack::push_pop(*this); - stack::push(base_t::lua_state(), lua_nil); - while (lua_next(base_t::lua_state(), -2)) { - object key(base_t::lua_state(), -2); - object value(base_t::lua_state(), -1); - auto pn = stack::pop_n(base_t::lua_state(), 1); - fx(key, value); - } - } - - template - auto tuple_get(types, std::index_sequence<0, 1, I...>, Keys&& keys) const - -> decltype(stack::pop>(nullptr)) { - typedef decltype(stack::pop>(nullptr)) Tup; - return Tup(traverse_get_optional(meta::is_optional>(), std::get<0>(std::forward(keys))), - traverse_get_optional(meta::is_optional>(), std::get<1>(std::forward(keys))), - traverse_get_optional(meta::is_optional>(), std::get(std::forward(keys)))...); - } - - template - decltype(auto) tuple_get(types, std::index_sequence, Keys&& keys) const { - return traverse_get_optional(meta::is_optional>(), std::get(std::forward(keys))); - } - - template - void tuple_set(std::index_sequence, Pairs&& pairs) { - auto pp = stack::push_pop < top_level && (is_global(std::forward(pairs)))...>::value) > (*this); - void(detail::swallow{ (stack::set_field(base_t::lua_state(), - std::get(std::forward(pairs)), - std::get(std::forward(pairs)), - lua_gettop(base_t::lua_state())), - 0)... }); - } - - template - decltype(auto) traverse_get_deep(Key&& key) const { - stack::get_field(base_t::lua_state(), std::forward(key)); - return stack::get(base_t::lua_state()); - } - - template - decltype(auto) traverse_get_deep(Key&& key, Keys&&... keys) const { - stack::get_field(base_t::lua_state(), std::forward(key)); - return traverse_get_deep(std::forward(keys)...); - } - - template - decltype(auto) traverse_get_deep_optional(int& popcount, Key&& key) const { - typedef decltype(stack::get(base_t::lua_state())) R; - auto p = stack::probe_get_field(base_t::lua_state(), std::forward(key), lua_gettop(base_t::lua_state())); - popcount += p.levels; - if (!p.success) - return R(nullopt); - return stack::get(base_t::lua_state()); - } - - template - decltype(auto) traverse_get_deep_optional(int& popcount, Key&& key, Keys&&... keys) const { - auto p = I > 0 ? stack::probe_get_field(base_t::lua_state(), std::forward(key), -1) - : stack::probe_get_field(base_t::lua_state(), std::forward(key), lua_gettop(base_t::lua_state())); - popcount += p.levels; - if (!p.success) - return T(nullopt); - return traverse_get_deep_optional(popcount, std::forward(keys)...); - } - - template - decltype(auto) traverse_get_optional(std::false_type, Keys&&... keys) const { - detail::clean c(base_t::lua_state()); - return traverse_get_deep(std::forward(keys)...); - } - - template - decltype(auto) traverse_get_optional(std::true_type, Keys&&... keys) const { - int popcount = 0; - detail::ref_clean c(base_t::lua_state(), popcount); - return traverse_get_deep_optional(popcount, std::forward(keys)...); - } - - template - void traverse_set_deep(Key&& key, Value&& value) const { - stack::set_field(base_t::lua_state(), std::forward(key), std::forward(value)); - } - - template - void traverse_set_deep(Key&& key, Keys&&... keys) const { - stack::get_field(base_t::lua_state(), std::forward(key)); - traverse_set_deep(std::forward(keys)...); - } - - basic_table_core(lua_State* L, detail::global_tag t) noexcept : base_t(L, t) { - } - - protected: - basic_table_core(detail::no_safety_tag, lua_nil_t n) : base_t(n) { - } - basic_table_core(detail::no_safety_tag, lua_State* L, int index) : base_t(L, index) { - } - basic_table_core(detail::no_safety_tag, lua_State* L, ref_index index) : base_t(L, index) { - } - template , basic_table_core>>, meta::neg>, - meta::neg>>, is_lua_reference>> = meta::enabler> - basic_table_core(detail::no_safety_tag, T&& r) noexcept : base_t(std::forward(r)) { - } - template >> = meta::enabler> - basic_table_core(detail::no_safety_tag, lua_State* L, T&& r) noexcept : base_t(L, std::forward(r)) { - } - - public: - typedef basic_table_iterator iterator; - typedef iterator const_iterator; - - using base_t::lua_state; - - basic_table_core() noexcept = default; - basic_table_core(const basic_table_core&) = default; - basic_table_core(basic_table_core&&) = default; - basic_table_core& operator=(const basic_table_core&) = default; - basic_table_core& operator=(basic_table_core&&) = default; - basic_table_core(const stack_reference& r) : basic_table_core(r.lua_state(), r.stack_index()) { - } - basic_table_core(stack_reference&& r) : basic_table_core(r.lua_state(), r.stack_index()) { - } - template >> = meta::enabler> - basic_table_core(lua_State* L, T&& r) : base_t(L, std::forward(r)) { -#if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES - auto pp = stack::push_pop(*this); - constructor_handler handler{}; - stack::check(lua_state(), -1, handler); -#endif // Safety - } - basic_table_core(lua_State* L, const new_table& nt) : base_t(L, -stack::push(L, nt)) { - if (!is_stack_based>::value) { - lua_pop(L, 1); - } - } - basic_table_core(lua_State* L, int index = -1) : basic_table_core(detail::no_safety, L, index) { -#if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES - constructor_handler handler{}; - stack::check(L, index, handler); -#endif // Safety - } - basic_table_core(lua_State* L, ref_index index) : basic_table_core(detail::no_safety, L, index) { -#if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES - auto pp = stack::push_pop(*this); - constructor_handler handler{}; - stack::check(lua_state(), -1, handler); -#endif // Safety - } - template , basic_table_core>>, meta::neg>, - meta::neg>>, is_lua_reference>> = meta::enabler> - basic_table_core(T&& r) noexcept : basic_table_core(detail::no_safety, std::forward(r)) { -#if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES - if (!is_table>::value) { - auto pp = stack::push_pop(*this); - constructor_handler handler{}; - stack::check(base_t::lua_state(), -1, handler); - } -#endif // Safety - } - basic_table_core(lua_nil_t r) noexcept : basic_table_core(detail::no_safety, r) { - } - - iterator begin() const { - return iterator(*this); - } - - iterator end() const { - return iterator(); - } - - const_iterator cbegin() const { - return begin(); - } - - const_iterator cend() const { - return end(); - } - - template - decltype(auto) get(Keys&&... keys) const { - static_assert(sizeof...(Keys) == sizeof...(Ret), "number of keys and number of return types do not match"); - auto pp = stack::push_pop::value>(*this); - return tuple_get(types(), std::make_index_sequence(), std::forward_as_tuple(std::forward(keys)...)); - } - - template - decltype(auto) get_or(Key&& key, T&& otherwise) const { - typedef decltype(get("")) U; - optional option = get>(std::forward(key)); - if (option) { - return static_cast(option.value()); - } - return static_cast(std::forward(otherwise)); - } - - template - decltype(auto) get_or(Key&& key, D&& otherwise) const { - optional option = get>(std::forward(key)); - if (option) { - return static_cast(option.value()); - } - return static_cast(std::forward(otherwise)); - } - - template - decltype(auto) traverse_get(Keys&&... keys) const { - auto pp = stack::push_pop::value>(*this); - return traverse_get_optional(meta::is_optional>(), std::forward(keys)...); - } - - template - basic_table_core& traverse_set(Keys&&... keys) { - auto pp = stack::push_pop::value>(*this); - auto pn = stack::pop_n(base_t::lua_state(), static_cast(sizeof...(Keys) - 2)); - traverse_set_deep(std::forward(keys)...); - return *this; - } - - template - basic_table_core& set(Args&&... args) { - tuple_set(std::make_index_sequence(), std::forward_as_tuple(std::forward(args)...)); - return *this; - } - - template - decltype(auto) raw_get(Keys&&... keys) const { - static_assert(sizeof...(Keys) == sizeof...(Ret), "number of keys and number of return types do not match"); - auto pp = stack::push_pop::value>(*this); - return tuple_get(types(), std::make_index_sequence(), std::forward_as_tuple(std::forward(keys)...)); - } - - template - decltype(auto) raw_get_or(Key&& key, T&& otherwise) const { - typedef decltype(raw_get("")) U; - optional option = raw_get>(std::forward(key)); - if (option) { - return static_cast(option.value()); - } - return static_cast(std::forward(otherwise)); - } - - template - decltype(auto) raw_get_or(Key&& key, D&& otherwise) const { - optional option = raw_get>(std::forward(key)); - if (option) { - return static_cast(option.value()); - } - return static_cast(std::forward(otherwise)); - } - - template - decltype(auto) traverse_raw_get(Keys&&... keys) const { - auto pp = stack::push_pop::value>(*this); - return traverse_get_optional(meta::is_optional>(), std::forward(keys)...); - } - - template - basic_table_core& traverse_raw_set(Keys&&... keys) { - auto pp = stack::push_pop::value>(*this); - auto pn = stack::pop_n(base_t::lua_state(), static_cast(sizeof...(Keys) - 2)); - traverse_set_deep(std::forward(keys)...); - return *this; - } - - template - basic_table_core& raw_set(Args&&... args) { - tuple_set(std::make_index_sequence(), std::forward_as_tuple(std::forward(args)...)); - return *this; - } - - template - usertype new_usertype(Key&& key); - - template - usertype new_usertype(Key&& key, automagic_enrollments enrollment); - - template , automagic_enrollments>>> - usertype new_usertype(Key&& key, Arg&& arg, Args&&... args); - - template - table new_enum(const string_view& name, Args&&... args) { - table target = create_with(std::forward(args)...); - if (read_only) { - table x = create_with(meta_function::new_index, detail::fail_on_newindex, meta_function::index, target); - table shim = create_named(name, metatable_key, x); - return shim; - } - else { - set(name, target); - return target; - } - } - - template - table new_enum(const string_view& name, std::initializer_list> items) { - table target = create(static_cast(items.size()), static_cast(0)); - for (const auto& kvp : items) { - target.set(kvp.first, kvp.second); - } - if (read_only) { - table x = create_with(meta_function::new_index, detail::fail_on_newindex, meta_function::index, target); - table shim = create_named(name, metatable_key, x); - return shim; - } - else { - set(name, target); - return target; - } - } - - template - void for_each(Fx&& fx) const { - typedef meta::is_invokable)> is_paired; - for_each(is_paired(), std::forward(fx)); - } - - size_t size() const { - auto pp = stack::push_pop(*this); - lua_len(base_t::lua_state(), -1); - return stack::pop(base_t::lua_state()); - } - - bool empty() const { - return cbegin() == cend(); - } - - template - proxy operator[](T&& key) & { - return proxy(*this, std::forward(key)); - } - - template - proxy operator[](T&& key) const& { - return proxy(*this, std::forward(key)); - } - - template - proxy operator[](T&& key) && { - return proxy(*this, std::forward(key)); - } - - template - basic_table_core& set_function(Key&& key, Args&&... args) { - set_fx(types(), std::forward(key), std::forward(args)...); - return *this; - } - - template - basic_table_core& set_function(Key&& key, Args&&... args) { - set_fx(types<>(), std::forward(key), std::forward(args)...); - return *this; - } - - template - basic_table_core& add(Args&&... args) { - auto pp = stack::push_pop(*this); - (void)detail::swallow{ 0, (stack::set_ref(base_t::lua_state(), std::forward(args)), 0)... }; - return *this; - } - - private: - template > - void set_fx(types, Key&& key, Fx&& fx) { - set_resolved_function(std::forward(key), std::forward(fx)); - } - - template , overload_set>> = meta::enabler> - void set_fx(types<>, Key&& key, Fx&& fx) { - set(std::forward(key), std::forward(fx)); - } - - template , overload_set>> = meta::enabler> - void set_fx(types<>, Key&& key, Fx&& fx, Args&&... args) { - set(std::forward(key), as_function_reference(std::forward(fx), std::forward(args)...)); - } - - template - void set_resolved_function(Key&& key, Args&&... args) { - set(std::forward(key), as_function_reference>(std::forward(args)...)); - } - - public: - static inline table create(lua_State* L, int narr = 0, int nrec = 0) { - lua_createtable(L, narr, nrec); - table result(L); - lua_pop(L, 1); - return result; - } - - template - static inline table create(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { - lua_createtable(L, narr, nrec); - table result(L); - result.set(std::forward(key), std::forward(value), std::forward(args)...); - lua_pop(L, 1); - return result; - } - - template - static inline table create_with(lua_State* L, Args&&... args) { - static_assert(sizeof...(Args) % 2 == 0, "You must have an even number of arguments for a key, value ... list."); - static const int narr = static_cast(meta::count_2_for_pack::value); - return create(L, narr, static_cast((sizeof...(Args) / 2) - narr), std::forward(args)...); - } - - table create(int narr = 0, int nrec = 0) { - return create(base_t::lua_state(), narr, nrec); - } - - template - table create(int narr, int nrec, Key&& key, Value&& value, Args&&... args) { - return create(base_t::lua_state(), narr, nrec, std::forward(key), std::forward(value), std::forward(args)...); - } - - template - table create(Name&& name, int narr = 0, int nrec = 0) { - table x = create(base_t::lua_state(), narr, nrec); - this->set(std::forward(name), x); - return x; - } - - template - table create(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { - table x = create(base_t::lua_state(), narr, nrec, std::forward(key), std::forward(value), std::forward(args)...); - this->set(std::forward(name), x); - return x; - } - - template - table create_with(Args&&... args) { - return create_with(base_t::lua_state(), std::forward(args)...); - } - - template - table create_named(Name&& name, Args&&... args) { - static const int narr = static_cast(meta::count_2_for_pack::value); - return create(std::forward(name), narr, (sizeof...(Args) / 2) - narr, std::forward(args)...); - } - }; -} // namespace sol - -// end of sol/table_core.hpp - // beginning of sol/usertype.hpp // beginning of sol/usertype_core.hpp @@ -20111,10 +19614,9 @@ namespace sol { namespace u_detail { void* derived_this = static_cast(static_cast*>(this)); index_call_storage ics; ics.binding_data = b.data(); - //ics.index = is_index ? static_cast(&Binding::call_with_) - // : static_cast(&Binding::index_call_with_); - //ics.new_index = is_new_index ? static_cast(&Binding::call_with_) - // : static_cast(&Binding::index_call_with_); + ics.index = is_index ? &Binding::template call_with_ : &Binding::template index_call_with_; + ics.new_index = is_new_index ? &Binding::template call_with_ + : &Binding::template index_call_with_; // need to swap everything to use fast indexing here auto for_each_backing_metatable = [&](lua_State* L, submetatable_type smt, reference& fast_index_table) { if (smt == submetatable_type::named) { @@ -20223,7 +19725,7 @@ namespace sol { namespace u_detail { // we create a metatable to attach to the regular gc_table // so that the destructor is called for the usertype storage int usertype_storage_metatabe_count = stack::push(L, new_table(0, 1)); - stack_table usertype_storage_metatable(L, -usertype_storage_metatabe_count); + stack_reference usertype_storage_metatable(L, -usertype_storage_metatabe_count); // set the destruction routine on the metatable stack::set_field(L, meta_function::garbage_collect, detail::user_alloc_destruct>, usertype_storage_metatable.stack_index()); // set the metatable on the usertype storage userdata @@ -20751,6 +20253,503 @@ namespace sol { // end of sol/usertype.hpp +namespace sol { + namespace detail { + template + struct clean { + lua_State* L; + clean(lua_State* luastate) : L(luastate) { + } + ~clean() { + lua_pop(L, static_cast(n)); + } + }; + struct ref_clean { + lua_State* L; + int& n; + ref_clean(lua_State* luastate, int& n) : L(luastate), n(n) { + } + ~ref_clean() { + lua_pop(L, static_cast(n)); + } + }; + inline int fail_on_newindex(lua_State* L) { + return luaL_error(L, "sol: cannot modify the elements of an enumeration table"); + } + } // namespace detail + + template + class basic_table_core : public basic_object_base { + typedef basic_object_base base_t; + friend class state; + friend class state_view; + + template + using is_global = meta::all, meta::is_c_str...>; + + template + void for_each(std::true_type, Fx&& fx) const { + auto pp = stack::push_pop(*this); + stack::push(base_t::lua_state(), lua_nil); + while (lua_next(base_t::lua_state(), -2)) { + object key(base_t::lua_state(), -2); + object value(base_t::lua_state(), -1); + std::pair keyvalue(key, value); + auto pn = stack::pop_n(base_t::lua_state(), 1); + fx(keyvalue); + } + } + + template + void for_each(std::false_type, Fx&& fx) const { + auto pp = stack::push_pop(*this); + stack::push(base_t::lua_state(), lua_nil); + while (lua_next(base_t::lua_state(), -2)) { + object key(base_t::lua_state(), -2); + object value(base_t::lua_state(), -1); + auto pn = stack::pop_n(base_t::lua_state(), 1); + fx(key, value); + } + } + + template + auto tuple_get(types, std::index_sequence<0, 1, I...>, Keys&& keys) const + -> decltype(stack::pop>(nullptr)) { + typedef decltype(stack::pop>(nullptr)) Tup; + return Tup(traverse_get_optional(meta::is_optional>(), std::get<0>(std::forward(keys))), + traverse_get_optional(meta::is_optional>(), std::get<1>(std::forward(keys))), + traverse_get_optional(meta::is_optional>(), std::get(std::forward(keys)))...); + } + + template + decltype(auto) tuple_get(types, std::index_sequence, Keys&& keys) const { + return traverse_get_optional(meta::is_optional>(), std::get(std::forward(keys))); + } + + template + void tuple_set(std::index_sequence, Pairs&& pairs) { + auto pp = stack::push_pop < top_level && (is_global(std::forward(pairs)))...>::value) > (*this); + void(detail::swallow{ (stack::set_field(base_t::lua_state(), + std::get(std::forward(pairs)), + std::get(std::forward(pairs)), + lua_gettop(base_t::lua_state())), + 0)... }); + } + + template + decltype(auto) traverse_get_deep(Key&& key) const { + stack::get_field(base_t::lua_state(), std::forward(key)); + return stack::get(base_t::lua_state()); + } + + template + decltype(auto) traverse_get_deep(Key&& key, Keys&&... keys) const { + stack::get_field(base_t::lua_state(), std::forward(key)); + return traverse_get_deep(std::forward(keys)...); + } + + template + decltype(auto) traverse_get_deep_optional(int& popcount, Key&& key) const { + typedef decltype(stack::get(base_t::lua_state())) R; + auto p = stack::probe_get_field(base_t::lua_state(), std::forward(key), lua_gettop(base_t::lua_state())); + popcount += p.levels; + if (!p.success) + return R(nullopt); + return stack::get(base_t::lua_state()); + } + + template + decltype(auto) traverse_get_deep_optional(int& popcount, Key&& key, Keys&&... keys) const { + auto p = I > 0 ? stack::probe_get_field(base_t::lua_state(), std::forward(key), -1) + : stack::probe_get_field(base_t::lua_state(), std::forward(key), lua_gettop(base_t::lua_state())); + popcount += p.levels; + if (!p.success) + return T(nullopt); + return traverse_get_deep_optional(popcount, std::forward(keys)...); + } + + template + decltype(auto) traverse_get_optional(std::false_type, Keys&&... keys) const { + detail::clean c(base_t::lua_state()); + return traverse_get_deep(std::forward(keys)...); + } + + template + decltype(auto) traverse_get_optional(std::true_type, Keys&&... keys) const { + int popcount = 0; + detail::ref_clean c(base_t::lua_state(), popcount); + return traverse_get_deep_optional(popcount, std::forward(keys)...); + } + + template + void traverse_set_deep(Key&& key, Value&& value) const { + stack::set_field(base_t::lua_state(), std::forward(key), std::forward(value)); + } + + template + void traverse_set_deep(Key&& key, Keys&&... keys) const { + stack::get_field(base_t::lua_state(), std::forward(key)); + traverse_set_deep(std::forward(keys)...); + } + + basic_table_core(lua_State* L, detail::global_tag t) noexcept : base_t(L, t) { + } + + protected: + basic_table_core(detail::no_safety_tag, lua_nil_t n) : base_t(n) { + } + basic_table_core(detail::no_safety_tag, lua_State* L, int index) : base_t(L, index) { + } + basic_table_core(detail::no_safety_tag, lua_State* L, ref_index index) : base_t(L, index) { + } + template , basic_table_core>>, meta::neg>, + meta::neg>>, is_lua_reference>> = meta::enabler> + basic_table_core(detail::no_safety_tag, T&& r) noexcept : base_t(std::forward(r)) { + } + template >> = meta::enabler> + basic_table_core(detail::no_safety_tag, lua_State* L, T&& r) noexcept : base_t(L, std::forward(r)) { + } + + public: + typedef basic_table_iterator iterator; + typedef iterator const_iterator; + + using base_t::lua_state; + + basic_table_core() noexcept = default; + basic_table_core(const basic_table_core&) = default; + basic_table_core(basic_table_core&&) = default; + basic_table_core& operator=(const basic_table_core&) = default; + basic_table_core& operator=(basic_table_core&&) = default; + basic_table_core(const stack_reference& r) : basic_table_core(r.lua_state(), r.stack_index()) { + } + basic_table_core(stack_reference&& r) : basic_table_core(r.lua_state(), r.stack_index()) { + } + template >> = meta::enabler> + basic_table_core(lua_State* L, T&& r) : base_t(L, std::forward(r)) { +#if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES + auto pp = stack::push_pop(*this); + constructor_handler handler{}; + stack::check(lua_state(), -1, handler); +#endif // Safety + } + basic_table_core(lua_State* L, const new_table& nt) : base_t(L, -stack::push(L, nt)) { + if (!is_stack_based>::value) { + lua_pop(L, 1); + } + } + basic_table_core(lua_State* L, int index = -1) : basic_table_core(detail::no_safety, L, index) { +#if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES + constructor_handler handler{}; + stack::check(L, index, handler); +#endif // Safety + } + basic_table_core(lua_State* L, ref_index index) : basic_table_core(detail::no_safety, L, index) { +#if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES + auto pp = stack::push_pop(*this); + constructor_handler handler{}; + stack::check(lua_state(), -1, handler); +#endif // Safety + } + template , basic_table_core>>, meta::neg>, + meta::neg>>, is_lua_reference>> = meta::enabler> + basic_table_core(T&& r) noexcept : basic_table_core(detail::no_safety, std::forward(r)) { +#if defined(SOL_SAFE_REFERENCES) && SOL_SAFE_REFERENCES + if (!is_table>::value) { + auto pp = stack::push_pop(*this); + constructor_handler handler{}; + stack::check(base_t::lua_state(), -1, handler); + } +#endif // Safety + } + basic_table_core(lua_nil_t r) noexcept : basic_table_core(detail::no_safety, r) { + } + + iterator begin() const { + return iterator(*this); + } + + iterator end() const { + return iterator(); + } + + const_iterator cbegin() const { + return begin(); + } + + const_iterator cend() const { + return end(); + } + + template + decltype(auto) get(Keys&&... keys) const { + static_assert(sizeof...(Keys) == sizeof...(Ret), "number of keys and number of return types do not match"); + auto pp = stack::push_pop::value>(*this); + return tuple_get(types(), std::make_index_sequence(), std::forward_as_tuple(std::forward(keys)...)); + } + + template + decltype(auto) get_or(Key&& key, T&& otherwise) const { + typedef decltype(get("")) U; + optional option = get>(std::forward(key)); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) get_or(Key&& key, D&& otherwise) const { + optional option = get>(std::forward(key)); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) traverse_get(Keys&&... keys) const { + auto pp = stack::push_pop::value>(*this); + return traverse_get_optional(meta::is_optional>(), std::forward(keys)...); + } + + template + basic_table_core& traverse_set(Keys&&... keys) { + auto pp = stack::push_pop::value>(*this); + auto pn = stack::pop_n(base_t::lua_state(), static_cast(sizeof...(Keys) - 2)); + traverse_set_deep(std::forward(keys)...); + return *this; + } + + template + basic_table_core& set(Args&&... args) { + tuple_set(std::make_index_sequence(), std::forward_as_tuple(std::forward(args)...)); + return *this; + } + + template + decltype(auto) raw_get(Keys&&... keys) const { + static_assert(sizeof...(Keys) == sizeof...(Ret), "number of keys and number of return types do not match"); + auto pp = stack::push_pop::value>(*this); + return tuple_get(types(), std::make_index_sequence(), std::forward_as_tuple(std::forward(keys)...)); + } + + template + decltype(auto) raw_get_or(Key&& key, T&& otherwise) const { + typedef decltype(raw_get("")) U; + optional option = raw_get>(std::forward(key)); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) raw_get_or(Key&& key, D&& otherwise) const { + optional option = raw_get>(std::forward(key)); + if (option) { + return static_cast(option.value()); + } + return static_cast(std::forward(otherwise)); + } + + template + decltype(auto) traverse_raw_get(Keys&&... keys) const { + auto pp = stack::push_pop::value>(*this); + return traverse_get_optional(meta::is_optional>(), std::forward(keys)...); + } + + template + basic_table_core& traverse_raw_set(Keys&&... keys) { + auto pp = stack::push_pop::value>(*this); + auto pn = stack::pop_n(base_t::lua_state(), static_cast(sizeof...(Keys) - 2)); + traverse_set_deep(std::forward(keys)...); + return *this; + } + + template + basic_table_core& raw_set(Args&&... args) { + tuple_set(std::make_index_sequence(), std::forward_as_tuple(std::forward(args)...)); + return *this; + } + + template + usertype new_usertype(Key&& key); + + template + usertype new_usertype(Key&& key, automagic_enrollments enrollment); + + template , automagic_enrollments>>> + usertype new_usertype(Key&& key, Arg&& arg, Args&&... args); + + template + table new_enum(const string_view& name, Args&&... args) { + table target = create_with(std::forward(args)...); + if (read_only) { + table x = create_with(meta_function::new_index, detail::fail_on_newindex, meta_function::index, target); + table shim = create_named(name, metatable_key, x); + return shim; + } + else { + set(name, target); + return target; + } + } + + template + table new_enum(const string_view& name, std::initializer_list> items) { + table target = create(static_cast(items.size()), static_cast(0)); + for (const auto& kvp : items) { + target.set(kvp.first, kvp.second); + } + if (read_only) { + table x = create_with(meta_function::new_index, detail::fail_on_newindex, meta_function::index, target); + table shim = create_named(name, metatable_key, x); + return shim; + } + else { + set(name, target); + return target; + } + } + + template + void for_each(Fx&& fx) const { + typedef meta::is_invokable)> is_paired; + for_each(is_paired(), std::forward(fx)); + } + + size_t size() const { + auto pp = stack::push_pop(*this); + lua_len(base_t::lua_state(), -1); + return stack::pop(base_t::lua_state()); + } + + bool empty() const { + return cbegin() == cend(); + } + + template + proxy operator[](T&& key) & { + return proxy(*this, std::forward(key)); + } + + template + proxy operator[](T&& key) const& { + return proxy(*this, std::forward(key)); + } + + template + proxy operator[](T&& key) && { + return proxy(*this, std::forward(key)); + } + + template + basic_table_core& set_function(Key&& key, Args&&... args) { + set_fx(types(), std::forward(key), std::forward(args)...); + return *this; + } + + template + basic_table_core& set_function(Key&& key, Args&&... args) { + set_fx(types<>(), std::forward(key), std::forward(args)...); + return *this; + } + + template + basic_table_core& add(Args&&... args) { + auto pp = stack::push_pop(*this); + (void)detail::swallow{ 0, (stack::set_ref(base_t::lua_state(), std::forward(args)), 0)... }; + return *this; + } + + private: + template > + void set_fx(types, Key&& key, Fx&& fx) { + set_resolved_function(std::forward(key), std::forward(fx)); + } + + template , overload_set>> = meta::enabler> + void set_fx(types<>, Key&& key, Fx&& fx) { + set(std::forward(key), std::forward(fx)); + } + + template , overload_set>> = meta::enabler> + void set_fx(types<>, Key&& key, Fx&& fx, Args&&... args) { + set(std::forward(key), as_function_reference(std::forward(fx), std::forward(args)...)); + } + + template + void set_resolved_function(Key&& key, Args&&... args) { + set(std::forward(key), as_function_reference>(std::forward(args)...)); + } + + public: + static inline table create(lua_State* L, int narr = 0, int nrec = 0) { + lua_createtable(L, narr, nrec); + table result(L); + lua_pop(L, 1); + return result; + } + + template + static inline table create(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + lua_createtable(L, narr, nrec); + table result(L); + result.set(std::forward(key), std::forward(value), std::forward(args)...); + lua_pop(L, 1); + return result; + } + + template + static inline table create_with(lua_State* L, Args&&... args) { + static_assert(sizeof...(Args) % 2 == 0, "You must have an even number of arguments for a key, value ... list."); + static const int narr = static_cast(meta::count_2_for_pack::value); + return create(L, narr, static_cast((sizeof...(Args) / 2) - narr), std::forward(args)...); + } + + table create(int narr = 0, int nrec = 0) { + return create(base_t::lua_state(), narr, nrec); + } + + template + table create(int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + return create(base_t::lua_state(), narr, nrec, std::forward(key), std::forward(value), std::forward(args)...); + } + + template + table create(Name&& name, int narr = 0, int nrec = 0) { + table x = create(base_t::lua_state(), narr, nrec); + this->set(std::forward(name), x); + return x; + } + + template + table create(Name&& name, int narr, int nrec, Key&& key, Value&& value, Args&&... args) { + table x = create(base_t::lua_state(), narr, nrec, std::forward(key), std::forward(value), std::forward(args)...); + this->set(std::forward(name), x); + return x; + } + + template + table create_with(Args&&... args) { + return create_with(base_t::lua_state(), std::forward(args)...); + } + + template + table create_named(Name&& name, Args&&... args) { + static const int narr = static_cast(meta::count_2_for_pack::value); + return create(std::forward(name), narr, (sizeof...(Args) / 2) - narr, std::forward(args)...); + } + }; +} // namespace sol + +// end of sol/table_core.hpp + namespace sol { typedef table_core table; diff --git a/tests/compile_tests/CMakeLists.txt b/tests/compile_tests/CMakeLists.txt index 05137ef6..a8c50d85 100644 --- a/tests/compile_tests/CMakeLists.txt +++ b/tests/compile_tests/CMakeLists.txt @@ -22,14 +22,14 @@ # # # # sol3 tests - compilation tests -file(GLOB SOL2_COMPILE_TEST_SOURCES source/**/*.cpp) -source_group(compile_test_sources FILES ${SOL2_COMPILE_TEST_SOURCES}) +file(GLOB_RECURSE SOL2_COMPILE_TEST_SOURCES source/*.cpp) +source_group(compile_test_sources FILES "${SOL2_COMPILE_TEST_SOURCES}") function(CREATE_TEST test_target_name test_name target_sol) if (test_name MATCHES ".single") - add_executable(${test_target_name} source/main.cpp source/forward.cpp source/sol.cpp) + add_executable(${test_target_name} "source/main.cpp" "source/forward.cpp" "source/sol.cpp") else() - add_executable(${test_target_name} ${SOL2_COMPILE_TEST_SOURCES}) + add_executable(${test_target_name} "${SOL2_COMPILE_TEST_SOURCES}") endif() set_target_properties(${test_target_name} PROPERTIES @@ -69,10 +69,12 @@ function(CREATE_TEST test_target_name test_name target_sol) install(TARGETS ${test_target_name} RUNTIME DESTINATION bin) endfunction(CREATE_TEST) -CREATE_TEST(compile_tests "compile_tests" sol2::sol2) -if (SOL2_TESTS_SINGLE AND SOL2_SINGLE) +if (SOL2_TESTS) + CREATE_TEST(compile_tests "compile_tests" sol2::sol2) +endif() +if (SOL2_TESTS_SINGLE) CREATE_TEST(compile_tests_single "compile_tests.single" sol2::sol2_single) endif() -if (SOL2_TESTS_SINGLE_GENERATED AND SOL2_GENERATE_SINGLE) +if (SOL2_TESTS_SINGLE_GENERATED) CREATE_TEST(compile_tests_generated_single "compile_tests.single.generated" sol2::sol2_single_generated) endif() diff --git a/tests/compile_tests/source/as_args.cpp b/tests/compile_tests/source/as_args.cpp index 04bc7414..0a60ac69 100644 --- a/tests/compile_tests/source/as_args.cpp +++ b/tests/compile_tests/source/as_args.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/as_returns.cpp b/tests/compile_tests/source/as_returns.cpp index dd955c79..9f582a3c 100644 --- a/tests/compile_tests/source/as_returns.cpp +++ b/tests/compile_tests/source/as_returns.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/bind_traits.cpp b/tests/compile_tests/source/bind_traits.cpp index b6b6c225..ae894371 100644 --- a/tests/compile_tests/source/bind_traits.cpp +++ b/tests/compile_tests/source/bind_traits.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/call.cpp b/tests/compile_tests/source/call.cpp index 54ba7f5e..ef6f816d 100644 --- a/tests/compile_tests/source/call.cpp +++ b/tests/compile_tests/source/call.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/compatibility.cpp b/tests/compile_tests/source/compatibility.cpp index 40c3855e..f44ccc02 100644 --- a/tests/compile_tests/source/compatibility.cpp +++ b/tests/compile_tests/source/compatibility.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/compatibility/compat-5.3.cpp b/tests/compile_tests/source/compatibility/compat-5.3.cpp index 9f0244a4..7a64333a 100644 --- a/tests/compile_tests/source/compatibility/compat-5.3.cpp +++ b/tests/compile_tests/source/compatibility/compat-5.3.cpp @@ -23,4 +23,4 @@ #include "../sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/compatibility/version.cpp b/tests/compile_tests/source/compatibility/version.cpp index 80936aa8..d074bbae 100644 --- a/tests/compile_tests/source/compatibility/version.cpp +++ b/tests/compile_tests/source/compatibility/version.cpp @@ -23,4 +23,4 @@ #include "../sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/config.cpp b/tests/compile_tests/source/config.cpp index 17a3c767..2de2df40 100644 --- a/tests/compile_tests/source/config.cpp +++ b/tests/compile_tests/source/config.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/config_setup.cpp b/tests/compile_tests/source/config_setup.cpp index 2d3f15df..aa77017a 100644 --- a/tests/compile_tests/source/config_setup.cpp +++ b/tests/compile_tests/source/config_setup.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/container_traits.cpp b/tests/compile_tests/source/container_traits.cpp index db392eb0..4db25f14 100644 --- a/tests/compile_tests/source/container_traits.cpp +++ b/tests/compile_tests/source/container_traits.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/coroutine.cpp b/tests/compile_tests/source/coroutine.cpp index c4e94c03..96affdc7 100644 --- a/tests/compile_tests/source/coroutine.cpp +++ b/tests/compile_tests/source/coroutine.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/debug.cpp b/tests/compile_tests/source/debug.cpp index 583bbe36..14e0b052 100644 --- a/tests/compile_tests/source/debug.cpp +++ b/tests/compile_tests/source/debug.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/demangle.cpp b/tests/compile_tests/source/demangle.cpp index abe0b504..cce272e0 100644 --- a/tests/compile_tests/source/demangle.cpp +++ b/tests/compile_tests/source/demangle.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/deprecate.cpp b/tests/compile_tests/source/deprecate.cpp index 3ee84638..d29d0835 100644 --- a/tests/compile_tests/source/deprecate.cpp +++ b/tests/compile_tests/source/deprecate.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/environment.cpp b/tests/compile_tests/source/environment.cpp index 4231b3d8..16ec28fe 100644 --- a/tests/compile_tests/source/environment.cpp +++ b/tests/compile_tests/source/environment.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/error.cpp b/tests/compile_tests/source/error.cpp index 369a2e32..bc2dc874 100644 --- a/tests/compile_tests/source/error.cpp +++ b/tests/compile_tests/source/error.cpp @@ -1 +1 @@ -#include +#include diff --git a/tests/compile_tests/source/error_handler.cpp b/tests/compile_tests/source/error_handler.cpp index ad0a1128..f134bf84 100644 --- a/tests/compile_tests/source/error_handler.cpp +++ b/tests/compile_tests/source/error_handler.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/feature_test.cpp b/tests/compile_tests/source/feature_test.cpp index 46518325..a9ba4a13 100644 --- a/tests/compile_tests/source/feature_test.cpp +++ b/tests/compile_tests/source/feature_test.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/filters.cpp b/tests/compile_tests/source/filters.cpp index f6993e4d..8d2571bb 100644 --- a/tests/compile_tests/source/filters.cpp +++ b/tests/compile_tests/source/filters.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/forward.cpp b/tests/compile_tests/source/forward.cpp index 297b78ce..004009f0 100644 --- a/tests/compile_tests/source/forward.cpp +++ b/tests/compile_tests/source/forward.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/forward_detail.cpp b/tests/compile_tests/source/forward_detail.cpp index 008c812c..3cfcd815 100644 --- a/tests/compile_tests/source/forward_detail.cpp +++ b/tests/compile_tests/source/forward_detail.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/function.cpp b/tests/compile_tests/source/function.cpp index 1e62682b..4ae93a2b 100644 --- a/tests/compile_tests/source/function.cpp +++ b/tests/compile_tests/source/function.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/function_result.cpp b/tests/compile_tests/source/function_result.cpp index e73dce62..cd14962b 100644 --- a/tests/compile_tests/source/function_result.cpp +++ b/tests/compile_tests/source/function_result.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/function_types.cpp b/tests/compile_tests/source/function_types.cpp index c06d479a..2bbb90bf 100644 --- a/tests/compile_tests/source/function_types.cpp +++ b/tests/compile_tests/source/function_types.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/function_types_core.cpp b/tests/compile_tests/source/function_types_core.cpp index 8bd22ca6..d661fb72 100644 --- a/tests/compile_tests/source/function_types_core.cpp +++ b/tests/compile_tests/source/function_types_core.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/function_types_overloaded.cpp b/tests/compile_tests/source/function_types_overloaded.cpp index cbcf8583..a0cf539c 100644 --- a/tests/compile_tests/source/function_types_overloaded.cpp +++ b/tests/compile_tests/source/function_types_overloaded.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/function_types_stateful.cpp b/tests/compile_tests/source/function_types_stateful.cpp index f766e680..b318e950 100644 --- a/tests/compile_tests/source/function_types_stateful.cpp +++ b/tests/compile_tests/source/function_types_stateful.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/function_types_stateless.cpp b/tests/compile_tests/source/function_types_stateless.cpp index 4b894731..6c831247 100644 --- a/tests/compile_tests/source/function_types_stateless.cpp +++ b/tests/compile_tests/source/function_types_stateless.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/function_types_templated.cpp b/tests/compile_tests/source/function_types_templated.cpp index ebc607a1..08aa43e5 100644 --- a/tests/compile_tests/source/function_types_templated.cpp +++ b/tests/compile_tests/source/function_types_templated.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/in_place.cpp b/tests/compile_tests/source/in_place.cpp index 404da6c5..6086caf8 100644 --- a/tests/compile_tests/source/in_place.cpp +++ b/tests/compile_tests/source/in_place.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/inheritance.cpp b/tests/compile_tests/source/inheritance.cpp index bdcefca6..2fd858a7 100644 --- a/tests/compile_tests/source/inheritance.cpp +++ b/tests/compile_tests/source/inheritance.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/load_result.cpp b/tests/compile_tests/source/load_result.cpp index ed494ae1..f9ff5808 100644 --- a/tests/compile_tests/source/load_result.cpp +++ b/tests/compile_tests/source/load_result.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/make_reference.cpp b/tests/compile_tests/source/make_reference.cpp index 7bffed39..da4ac731 100644 --- a/tests/compile_tests/source/make_reference.cpp +++ b/tests/compile_tests/source/make_reference.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/map.cpp b/tests/compile_tests/source/map.cpp index 13e8fbe1..92d850b3 100644 --- a/tests/compile_tests/source/map.cpp +++ b/tests/compile_tests/source/map.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/metatable.cpp b/tests/compile_tests/source/metatable.cpp index 32786022..55e1f63a 100644 --- a/tests/compile_tests/source/metatable.cpp +++ b/tests/compile_tests/source/metatable.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/object.cpp b/tests/compile_tests/source/object.cpp index 22df7364..7fef23ca 100644 --- a/tests/compile_tests/source/object.cpp +++ b/tests/compile_tests/source/object.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/object_base.cpp b/tests/compile_tests/source/object_base.cpp index 848cbf8b..bd5a436a 100644 --- a/tests/compile_tests/source/object_base.cpp +++ b/tests/compile_tests/source/object_base.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/optional.cpp b/tests/compile_tests/source/optional.cpp index 73e1ca51..9d58d770 100644 --- a/tests/compile_tests/source/optional.cpp +++ b/tests/compile_tests/source/optional.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/optional_implementation.cpp b/tests/compile_tests/source/optional_implementation.cpp index 45993806..14b7a8b2 100644 --- a/tests/compile_tests/source/optional_implementation.cpp +++ b/tests/compile_tests/source/optional_implementation.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/overload.cpp b/tests/compile_tests/source/overload.cpp index f0a093fe..ea5d5810 100644 --- a/tests/compile_tests/source/overload.cpp +++ b/tests/compile_tests/source/overload.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/property.cpp b/tests/compile_tests/source/property.cpp index f6c2ce5d..d465f58e 100644 --- a/tests/compile_tests/source/property.cpp +++ b/tests/compile_tests/source/property.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/protect.cpp b/tests/compile_tests/source/protect.cpp index 830e30ee..b486767a 100644 --- a/tests/compile_tests/source/protect.cpp +++ b/tests/compile_tests/source/protect.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/protected_function.cpp b/tests/compile_tests/source/protected_function.cpp index 92bf9119..af42ff14 100644 --- a/tests/compile_tests/source/protected_function.cpp +++ b/tests/compile_tests/source/protected_function.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/protected_function_result.cpp b/tests/compile_tests/source/protected_function_result.cpp index e7634f98..12d6ce6c 100644 --- a/tests/compile_tests/source/protected_function_result.cpp +++ b/tests/compile_tests/source/protected_function_result.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/protected_handler.cpp b/tests/compile_tests/source/protected_handler.cpp index 801508f5..d8cef055 100644 --- a/tests/compile_tests/source/protected_handler.cpp +++ b/tests/compile_tests/source/protected_handler.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/proxy.cpp b/tests/compile_tests/source/proxy.cpp index cc18b914..ff50e034 100644 --- a/tests/compile_tests/source/proxy.cpp +++ b/tests/compile_tests/source/proxy.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/proxy_base.cpp b/tests/compile_tests/source/proxy_base.cpp index f910b2bd..2febfa89 100644 --- a/tests/compile_tests/source/proxy_base.cpp +++ b/tests/compile_tests/source/proxy_base.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/raii.cpp b/tests/compile_tests/source/raii.cpp index d853f6e2..0a8eada3 100644 --- a/tests/compile_tests/source/raii.cpp +++ b/tests/compile_tests/source/raii.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/reference.cpp b/tests/compile_tests/source/reference.cpp index ac6f2438..adbb96f7 100644 --- a/tests/compile_tests/source/reference.cpp +++ b/tests/compile_tests/source/reference.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/resolve.cpp b/tests/compile_tests/source/resolve.cpp index 6a26dc29..9a9f0d62 100644 --- a/tests/compile_tests/source/resolve.cpp +++ b/tests/compile_tests/source/resolve.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/sol.cpp b/tests/compile_tests/source/sol.cpp index b0f29858..39e586b5 100644 --- a/tests/compile_tests/source/sol.cpp +++ b/tests/compile_tests/source/sol.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/stack.cpp b/tests/compile_tests/source/stack.cpp index 6a6670d4..e2debe2a 100644 --- a/tests/compile_tests/source/stack.cpp +++ b/tests/compile_tests/source/stack.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/stack_check.cpp b/tests/compile_tests/source/stack_check.cpp index c83e2f37..601597fe 100644 --- a/tests/compile_tests/source/stack_check.cpp +++ b/tests/compile_tests/source/stack_check.cpp @@ -23,4 +23,5 @@ #include "sol_defines.hpp" -#include +//#include +#include diff --git a/tests/compile_tests/source/stack_check_get.cpp b/tests/compile_tests/source/stack_check_get.cpp index 6522957e..145f4a30 100644 --- a/tests/compile_tests/source/stack_check_get.cpp +++ b/tests/compile_tests/source/stack_check_get.cpp @@ -23,4 +23,5 @@ #include "sol_defines.hpp" -#include +//#include +#include diff --git a/tests/compile_tests/source/stack_check_get_qualified.cpp b/tests/compile_tests/source/stack_check_get_qualified.cpp index f36e632d..e34dd1ca 100644 --- a/tests/compile_tests/source/stack_check_get_qualified.cpp +++ b/tests/compile_tests/source/stack_check_get_qualified.cpp @@ -23,4 +23,5 @@ #include "sol_defines.hpp" -#include +//#include +#include diff --git a/tests/compile_tests/source/stack_check_get_unqualified.cpp b/tests/compile_tests/source/stack_check_get_unqualified.cpp index 78df1967..fe05f2d3 100644 --- a/tests/compile_tests/source/stack_check_get_unqualified.cpp +++ b/tests/compile_tests/source/stack_check_get_unqualified.cpp @@ -23,4 +23,5 @@ #include "sol_defines.hpp" -#include +//#include +#include diff --git a/tests/compile_tests/source/stack_check_qualified.cpp b/tests/compile_tests/source/stack_check_qualified.cpp index e0764e72..09904c2e 100644 --- a/tests/compile_tests/source/stack_check_qualified.cpp +++ b/tests/compile_tests/source/stack_check_qualified.cpp @@ -23,4 +23,5 @@ #include "sol_defines.hpp" -#include +//#include +#include diff --git a/tests/compile_tests/source/stack_check_unqualified.cpp b/tests/compile_tests/source/stack_check_unqualified.cpp index a6d0e089..fcf24e1f 100644 --- a/tests/compile_tests/source/stack_check_unqualified.cpp +++ b/tests/compile_tests/source/stack_check_unqualified.cpp @@ -23,4 +23,5 @@ #include "sol_defines.hpp" -#include +//#include +#include diff --git a/tests/compile_tests/source/stack_core.cpp b/tests/compile_tests/source/stack_core.cpp index 01209a86..fe28e75b 100644 --- a/tests/compile_tests/source/stack_core.cpp +++ b/tests/compile_tests/source/stack_core.cpp @@ -1,26 +1,27 @@ -// sol3 - -// The MIT License (MIT) - -// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#include "sol_defines.hpp" - -#include +// sol3 + +// The MIT License (MIT) + +// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include "sol_defines.hpp" + +//#include +#include diff --git a/tests/compile_tests/source/stack_field.cpp b/tests/compile_tests/source/stack_field.cpp index 065c749a..5f1b3b64 100644 --- a/tests/compile_tests/source/stack_field.cpp +++ b/tests/compile_tests/source/stack_field.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/stack_get.cpp b/tests/compile_tests/source/stack_get.cpp index afbd1acf..1636790f 100644 --- a/tests/compile_tests/source/stack_get.cpp +++ b/tests/compile_tests/source/stack_get.cpp @@ -1,26 +1,27 @@ -// sol3 - -// The MIT License (MIT) - -// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#include "sol_defines.hpp" - -#include +// sol3 + +// The MIT License (MIT) + +// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include "sol_defines.hpp" + +//#include +#include diff --git a/tests/compile_tests/source/stack_get_qualified.cpp b/tests/compile_tests/source/stack_get_qualified.cpp index f6a249b9..7fb676e1 100644 --- a/tests/compile_tests/source/stack_get_qualified.cpp +++ b/tests/compile_tests/source/stack_get_qualified.cpp @@ -1,26 +1,27 @@ -// sol3 - -// The MIT License (MIT) - -// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#include "sol_defines.hpp" - -#include +// sol3 + +// The MIT License (MIT) + +// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include "sol_defines.hpp" + +//#include +#include diff --git a/tests/compile_tests/source/stack_get_unqualified.cpp b/tests/compile_tests/source/stack_get_unqualified.cpp index 36f6c5ea..fbf88527 100644 --- a/tests/compile_tests/source/stack_get_unqualified.cpp +++ b/tests/compile_tests/source/stack_get_unqualified.cpp @@ -1,26 +1,27 @@ -// sol3 - -// The MIT License (MIT) - -// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#include "sol_defines.hpp" - -#include +// sol3 + +// The MIT License (MIT) + +// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include "sol_defines.hpp" + +//#include +#include diff --git a/tests/compile_tests/source/stack_guard.cpp b/tests/compile_tests/source/stack_guard.cpp index 2f297b46..17d2f53d 100644 --- a/tests/compile_tests/source/stack_guard.cpp +++ b/tests/compile_tests/source/stack_guard.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/stack_iterator.cpp b/tests/compile_tests/source/stack_iterator.cpp index 119f7989..e308c38e 100644 --- a/tests/compile_tests/source/stack_iterator.cpp +++ b/tests/compile_tests/source/stack_iterator.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/stack_pop.cpp b/tests/compile_tests/source/stack_pop.cpp index 17518b5f..d16a0239 100644 --- a/tests/compile_tests/source/stack_pop.cpp +++ b/tests/compile_tests/source/stack_pop.cpp @@ -1,26 +1,27 @@ -// sol3 - -// The MIT License (MIT) - -// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors - -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#include "sol_defines.hpp" - -#include +// sol3 + +// The MIT License (MIT) + +// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include "sol_defines.hpp" + +//#include +#include diff --git a/tests/compile_tests/source/stack_probe.cpp b/tests/compile_tests/source/stack_probe.cpp index 7a00b9ee..d35257b2 100644 --- a/tests/compile_tests/source/stack_probe.cpp +++ b/tests/compile_tests/source/stack_probe.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/stack_proxy.cpp b/tests/compile_tests/source/stack_proxy.cpp index 05730c5b..d117da8e 100644 --- a/tests/compile_tests/source/stack_proxy.cpp +++ b/tests/compile_tests/source/stack_proxy.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/stack_proxy_base.cpp b/tests/compile_tests/source/stack_proxy_base.cpp index fd23f4ba..e1eb72ff 100644 --- a/tests/compile_tests/source/stack_proxy_base.cpp +++ b/tests/compile_tests/source/stack_proxy_base.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/stack_reference.cpp b/tests/compile_tests/source/stack_reference.cpp index 5d7ba02e..99f17571 100644 --- a/tests/compile_tests/source/stack_reference.cpp +++ b/tests/compile_tests/source/stack_reference.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/state.cpp b/tests/compile_tests/source/state.cpp index 19cfdf9b..227dfc20 100644 --- a/tests/compile_tests/source/state.cpp +++ b/tests/compile_tests/source/state.cpp @@ -1 +1 @@ -#include +#include diff --git a/tests/compile_tests/source/state_view.cpp b/tests/compile_tests/source/state_view.cpp index a06f38af..6f7730d5 100644 --- a/tests/compile_tests/source/state_view.cpp +++ b/tests/compile_tests/source/state_view.cpp @@ -1 +1 @@ -#include +#include diff --git a/tests/compile_tests/source/string_view.cpp b/tests/compile_tests/source/string_view.cpp index fb1ab483..f8b422b7 100644 --- a/tests/compile_tests/source/string_view.cpp +++ b/tests/compile_tests/source/string_view.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/table.cpp b/tests/compile_tests/source/table.cpp index 57f9a7a9..7f889fa9 100644 --- a/tests/compile_tests/source/table.cpp +++ b/tests/compile_tests/source/table.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/table_core.cpp b/tests/compile_tests/source/table_core.cpp index 0f1a87bb..092437ed 100644 --- a/tests/compile_tests/source/table_core.cpp +++ b/tests/compile_tests/source/table_core.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/table_iterator.cpp b/tests/compile_tests/source/table_iterator.cpp index 26fb1b55..7502cf51 100644 --- a/tests/compile_tests/source/table_iterator.cpp +++ b/tests/compile_tests/source/table_iterator.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/tie.cpp b/tests/compile_tests/source/tie.cpp index 74937360..67dd0137 100644 --- a/tests/compile_tests/source/tie.cpp +++ b/tests/compile_tests/source/tie.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/traits.cpp b/tests/compile_tests/source/traits.cpp index da5bc88e..697a3152 100644 --- a/tests/compile_tests/source/traits.cpp +++ b/tests/compile_tests/source/traits.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/trampoline.cpp b/tests/compile_tests/source/trampoline.cpp index 7718dfed..9700ae7f 100644 --- a/tests/compile_tests/source/trampoline.cpp +++ b/tests/compile_tests/source/trampoline.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/tuple.cpp b/tests/compile_tests/source/tuple.cpp index 19907d20..49d75f92 100644 --- a/tests/compile_tests/source/tuple.cpp +++ b/tests/compile_tests/source/tuple.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/types.cpp b/tests/compile_tests/source/types.cpp index 1c72d451..28610b5a 100644 --- a/tests/compile_tests/source/types.cpp +++ b/tests/compile_tests/source/types.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/unicode.cpp b/tests/compile_tests/source/unicode.cpp index ffda50a7..f1d80425 100644 --- a/tests/compile_tests/source/unicode.cpp +++ b/tests/compile_tests/source/unicode.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/unsafe_function.cpp b/tests/compile_tests/source/unsafe_function.cpp index 82afa3a2..594501c3 100644 --- a/tests/compile_tests/source/unsafe_function.cpp +++ b/tests/compile_tests/source/unsafe_function.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/unsafe_function_result.cpp b/tests/compile_tests/source/unsafe_function_result.cpp index 68b64304..3a23ffb5 100644 --- a/tests/compile_tests/source/unsafe_function_result.cpp +++ b/tests/compile_tests/source/unsafe_function_result.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/userdata.cpp b/tests/compile_tests/source/userdata.cpp index d7a66d4d..d01936d2 100644 --- a/tests/compile_tests/source/userdata.cpp +++ b/tests/compile_tests/source/userdata.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/usertype.cpp b/tests/compile_tests/source/usertype.cpp index 929f6d56..ff0d8d0b 100644 --- a/tests/compile_tests/source/usertype.cpp +++ b/tests/compile_tests/source/usertype.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/usertype_container.cpp b/tests/compile_tests/source/usertype_container.cpp index 1c991ae4..d150a11f 100644 --- a/tests/compile_tests/source/usertype_container.cpp +++ b/tests/compile_tests/source/usertype_container.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/usertype_core.cpp b/tests/compile_tests/source/usertype_core.cpp index 32002653..a8c2a22a 100644 --- a/tests/compile_tests/source/usertype_core.cpp +++ b/tests/compile_tests/source/usertype_core.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/usertype_proxy.cpp b/tests/compile_tests/source/usertype_proxy.cpp index 5dd7555d..54988f30 100644 --- a/tests/compile_tests/source/usertype_proxy.cpp +++ b/tests/compile_tests/source/usertype_proxy.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/usertype_storage.cpp b/tests/compile_tests/source/usertype_storage.cpp index e8a093ec..2b25bd54 100644 --- a/tests/compile_tests/source/usertype_storage.cpp +++ b/tests/compile_tests/source/usertype_storage.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/usertype_traits.cpp b/tests/compile_tests/source/usertype_traits.cpp index 2f57b20e..04df8ae1 100644 --- a/tests/compile_tests/source/usertype_traits.cpp +++ b/tests/compile_tests/source/usertype_traits.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/variadic_args.cpp b/tests/compile_tests/source/variadic_args.cpp index 7acfde4d..a3dcfb27 100644 --- a/tests/compile_tests/source/variadic_args.cpp +++ b/tests/compile_tests/source/variadic_args.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/variadic_results.cpp b/tests/compile_tests/source/variadic_results.cpp index 44e154ad..8087e854 100644 --- a/tests/compile_tests/source/variadic_results.cpp +++ b/tests/compile_tests/source/variadic_results.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/compile_tests/source/wrapper.cpp b/tests/compile_tests/source/wrapper.cpp index 35e8bd9a..bbe51c5b 100644 --- a/tests/compile_tests/source/wrapper.cpp +++ b/tests/compile_tests/source/wrapper.cpp @@ -23,4 +23,4 @@ #include "sol_defines.hpp" -#include +#include diff --git a/tests/runtime_tests/CMakeLists.txt b/tests/runtime_tests/CMakeLists.txt index 830deee1..38bbd8af 100644 --- a/tests/runtime_tests/CMakeLists.txt +++ b/tests/runtime_tests/CMakeLists.txt @@ -71,10 +71,12 @@ function(CREATE_TEST test_target_name test_name target_sol) install(TARGETS ${test_target_name} RUNTIME DESTINATION bin) endfunction(CREATE_TEST) -CREATE_TEST(runtime_tests "runtime_tests" sol2::sol2) -if (SOL2_TESTS_SINGLE AND SOL2_SINGLE) +if (SOL2_TESTS) + CREATE_TEST(runtime_tests "runtime_tests" sol2::sol2) +endif() +if (SOL2_TESTS_SINGLE) CREATE_TEST(runtime_tests_single "runtime_tests.single" sol2::sol2_single) endif() -if (SOL2_TESTS_SINGLE_GENERATED AND SOL2_GENERATE_SINGLE) +if (SOL2_TESTS_SINGLE_GENERATED) CREATE_TEST(runtime_tests_generated_single "runtime_tests.single.generated" sol2::sol2_single_generated) endif() diff --git a/tests/runtime_tests/source/common_classes.hpp b/tests/runtime_tests/source/common_classes.hpp new file mode 100644 index 00000000..46dad13d --- /dev/null +++ b/tests/runtime_tests/source/common_classes.hpp @@ -0,0 +1,153 @@ +// sol3 + +// The MIT License (MIT) + +// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#ifndef SOL_TESTS_COMMON_CLASSES_HPP +#define SOL_TESTS_COMMON_CLASSES_HPP + +#include + +struct non_copyable { + non_copyable(non_copyable&& other) noexcept = default; + non_copyable& operator=(non_copyable&& other) noexcept = default; + non_copyable(const non_copyable& other) noexcept = delete; + non_copyable& operator=(const non_copyable& other) noexcept = delete; +}; + +struct vars { + vars() { + } + + int boop = 0; + + ~vars() { + } +}; + +struct fuser { + int x; + fuser() : x(0) { + } + + fuser(int x) : x(x) { + } + + int add(int y) { + return x + y; + } + + int add2(int y) { + return x + y + 2; + } +}; + +namespace crapola { + struct fuser { + int x; + fuser() : x(0) { + } + fuser(int x) : x(x) { + } + fuser(int x, int x2) : x(x * x2) { + } + + int add(int y) { + return x + y; + } + int add2(int y) { + return x + y + 2; + } + }; +} // namespace crapola + +class Base { +public: + Base(int a_num) : m_num(a_num) { + } + + int get_num() { + return m_num; + } + +protected: + int m_num; +}; + +class Derived : public Base { +public: + Derived(int a_num) : Base(a_num) { + } + + int get_num_10() { + return 10 * m_num; + } +}; + +class abstract_A { +public: + virtual void a() = 0; +}; + +class abstract_B : public abstract_A { +public: + virtual void a() override { + std::cout << "overridden a() in B : public A - BARK" << std::endl; + } +}; + +struct Vec { + float x, y, z; + Vec(float x, float y, float z) : x{ x }, y{ y }, z{ z } { + } + float length() { + return sqrtf(x * x + y * y + z * z); + } + Vec normalized() { + float invS = 1 / length(); + return { x * invS, y * invS, z * invS }; + } +}; + +struct giver { + int a = 0; + + giver() { + } + + void gief() { + a = 1; + } + + static int stuff() { + std::cout << "stuff" << std::endl; + return 97; + } + + static void gief_stuff(giver& t, int a) { + t.a = a; + } + + ~giver() { + } +}; + +#endif // SOL_TESTS_COMMON_CLASSES_HPP \ No newline at end of file diff --git a/tests/runtime_tests/source/container_shims.cpp b/tests/runtime_tests/source/container_shims.cpp new file mode 100644 index 00000000..53f6dbfc --- /dev/null +++ b/tests/runtime_tests/source/container_shims.cpp @@ -0,0 +1,257 @@ +// sol3 + +// The MIT License (MIT) + +// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include "sol_test.hpp" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +class int_shim { +public: + int_shim() = default; + + int_shim(int x) : x_(x) { + } + + int val() const { + return x_; + } + +private: + int x_ = -1; +}; + +class input_it { +public: + typedef std::input_iterator_tag iterator_category; + typedef int_shim value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef value_type* pointer; + typedef std::ptrdiff_t difference_type; + + input_it() = default; + + input_it(int n, int m) : n_(n), m_(m), value_(n_) { + assert(n_ >= 0); + assert(m_ >= 0); + assert(n_ <= m_); + + if (!n_ && !m_) { + n_ = -1; + m_ = -1; + value_ = -1; + } + } + + const int_shim& operator*() const { + return value_; + } + + const int_shim* operator->() const { + return &value_; + } + + input_it& operator++() { + assert(n_ >= 0); + assert(m_ >= 0); + if (n_ == m_ - 1) { + n_ = m_ = -1; + } + else { + ++n_; + } + value_ = n_; + return *this; + } + + bool operator==(const input_it& i) const { + return n_ == i.n_ && m_ == i.m_; + } + + bool operator!=(const input_it& i) const { + return !(*this == i); + } + +private: + int n_ = -1; + int m_ = -1; + int_shim value_; +}; + +class not_really_a_container { +public: + using value_type = int_shim; + using iterator = input_it; + using const_iterator = input_it; + + const_iterator begin() const { + return iterator(0, 100); + } + + const_iterator end() const { + return iterator(); + } + + value_type gcc_warning_block() { + return int_shim(); + } + + std::size_t size() const { + return 100; + } +}; + +struct my_vec : public std::vector { + typedef std::vector base_t; + using base_t::base_t; +}; + +namespace sol { + template <> + struct is_container : std::true_type {}; + + template <> + struct container_traits { + static auto begin(lua_State*, my_vec& self) { + return self.begin(); + } + static auto end(lua_State*, my_vec& self) { + return self.end(); + } + static std::ptrdiff_t index_adjustment(lua_State*, my_vec&) { + return 0; + } + }; + +} // namespace sol + +TEST_CASE("containers/input iterators", "test shitty input iterators that are all kinds of B L E H") { + sol::state lua; + lua.open_libraries(sol::lib::base, sol::lib::package); + lua.new_usertype("int_shim", "new", sol::no_constructor, "val", &int_shim::val); + + not_really_a_container c; + lua["c"] = &c; +#if SOL_LUA_VERSION > 502 + auto result0 = lua.safe_script(R"lua( +for k, v in pairs(c) do + assert((k - 1) == v:val()) +end +)lua", + sol::script_pass_on_error); + REQUIRE(result0.valid()); + +#endif + auto result1 = lua.safe_script(R"lua( +for k=1,#c do + v = c[k] + assert((k - 1) == v:val()) +end +)lua", + sol::script_pass_on_error); + REQUIRE(result1.valid()); +} + +TEST_CASE("containers/custom indexing", "allow containers to set a custom indexing offset") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua["c"] = my_vec{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + + auto result1 = lua.safe_script("for i=0,9 do assert(i == c[i]) end", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto result2 = lua.safe_script("assert(c[10] == nil)", sol::script_pass_on_error); + REQUIRE(result2.valid()); + auto result3 = lua.safe_script("assert(c[-1] == nil)", sol::script_pass_on_error); + REQUIRE(result3.valid()); +} + +TEST_CASE("containers/containers of pointers", "containers of pointers shouldn't have their value_type's overly stripped") { + sol::state lua; + + class MyContainer { + public: + typedef int** iterator; + typedef int* value_type; + + std::vector m_vec; + + inline iterator begin() { + return m_vec.data(); + } + inline iterator end() { + return m_vec.data() + m_vec.size(); + } + inline void push_back(value_type v) { + m_vec.push_back(v); + } + }; + int a = 500; + int b = 600; + + MyContainer ctr; + ctr.push_back(&a); + ctr.push_back(&b); + lua["c"] = ctr; + { + auto result1 = lua.safe_script("ap = c[1]", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto result2 = lua.safe_script("bp = c[2]", sol::script_pass_on_error); + REQUIRE(result2.valid()); + int* ap = lua["ap"]; + int* bp = lua["bp"]; + REQUIRE(ap == &a); + REQUIRE(bp == &b); + REQUIRE(*ap == 500); + REQUIRE(*bp == 600); + } + + std::unordered_map ptrs; + ptrs[5] = &a; + ptrs[6] = &b; + lua["c2"] = ptrs; + { + auto result1 = lua.safe_script("ap = c2[5]", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto result2 = lua.safe_script("bp = c2[6]", sol::script_pass_on_error); + REQUIRE(result2.valid()); + int* ap = lua["ap"]; + int* bp = lua["bp"]; + REQUIRE(ap == &a); + REQUIRE(bp == &b); + REQUIRE(*ap == 500); + REQUIRE(*bp == 600); + } +} diff --git a/tests/runtime_tests/source/container_table.cpp b/tests/runtime_tests/source/container_table.cpp new file mode 100644 index 00000000..033d85e8 --- /dev/null +++ b/tests/runtime_tests/source/container_table.cpp @@ -0,0 +1,307 @@ +// sol3 + +// The MIT License (MIT) + +// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include "sol_test.hpp" +#include "common_classes.hpp" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +TEST_CASE("containers/vector table roundtrip", "make sure vectors can be round-tripped") { + sol::state lua; + std::vector v{ 1, 2, 3 }; + lua.set_function("f", [&]() { + return sol::as_table(v); + }); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); + sol::as_table_t> x = lua["x"]; + bool areequal = x.source == v; + REQUIRE(areequal); +} + +TEST_CASE("containers/deque table roundtrip", "make sure deques can be round-tripped") { + sol::state lua; + std::deque v{ 1, 2, 3 }; + lua.set_function("f", [&]() { + return sol::as_table(v); + }); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); + sol::as_table_t> x = lua["x"]; + bool areequal = x.source == v; + REQUIRE(areequal); +} + +TEST_CASE("containers/array table roundtrip", "make sure arrays can be round-tripped") { + sol::state lua; + std::array v{ { 1, 2, 3 } }; + lua.set_function("f", [&]() { + return sol::as_table(v); + }); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); + sol::as_table_t> x = lua["x"]; + bool areequal = x.source == v; + REQUIRE(areequal); +} + +TEST_CASE("containers/list table roundtrip", "make sure lists can be round-tripped") { + sol::state lua; + std::list v{ 1, 2, 3 }; + lua.set_function("f", [&]() { + return sol::as_table(v); + }); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); + sol::as_table_t> x = lua["x"]; + bool areequal = x.source == v; + REQUIRE(areequal); +} + +TEST_CASE("containers/forward_list table roundtrip", "make sure forward_lists can be round-tripped") { + sol::state lua; + std::forward_list v{ 1, 2, 3 }; + lua.set_function("f", [&]() { + return sol::as_table(v); + }); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); + sol::as_table_t> x = lua["x"]; + bool areequal = x.source == v; + REQUIRE(areequal); +} + +TEST_CASE("containers/map table roundtrip", "make sure maps can be round-tripped") { + sol::state lua; + std::map v{ { "a", 1 }, { "b", 2 }, { "c", 3 } }; + lua.set_function("f", [&]() { + return sol::as_table(v); + }); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); + sol::as_table_t> x = lua["x"]; + bool areequal = x.source == v; + REQUIRE(areequal); +} + +TEST_CASE("containers/unordered_map table roundtrip", "make sure unordered_maps can be round-tripped") { + sol::state lua; + std::unordered_map v{ { "a", 1 }, { "b", 2 }, { "c", 3 } }; + lua.set_function("f", [&]() { + return sol::as_table(v); + }); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); + sol::as_table_t> x = lua["x"]; + bool areequal = x.source == v; + REQUIRE(areequal); +} + +TEST_CASE("containers/unordered_set table roundtrip", "make sure unordered_sets can be round-tripped") { + sol::state lua; + std::unordered_set v{ 1, 2, 3 }; + lua.set_function("f", [&]() { + return sol::as_table(v); + }); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); + sol::as_table_t> x = lua["x"]; + bool areequal = x.source == v; + REQUIRE(areequal); +} + +TEST_CASE("containers/set table roundtrip", "make sure sets can be round-tripped") { + sol::state lua; + std::set v{ 1, 2, 3 }; + lua.set_function("f", [&]() { + return sol::as_table(v); + }); + auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); + REQUIRE(result1.valid()); + sol::as_table_t> x = lua["x"]; + bool areequal = x.source == v; + REQUIRE(areequal); +} + +TEST_CASE("containers/table conversions (lvalue)", "test table conversions with as_table and nested, when not directly serializing a temporary / new value") { + sol::state lua; + + auto f = []() { + std::vector response_words; + response_words.push_back("a"); + response_words.push_back("b"); + response_words.push_back("c"); + return sol::as_table(response_words); + }; + auto g = []() { + std::vector response_words; + response_words.push_back("a"); + response_words.push_back("b"); + response_words.push_back("c"); + return sol::as_nested(response_words); + }; + + lua["f"] = std::ref(f); + lua["g"] = std::ref(g); + + sol::safe_function sff = lua["f"]; + sol::safe_function sfg = lua["g"]; + sol::table tf = sff(); + sol::table tg = sfg(); + + std::string af = tf[1]; + std::string bf = tf[2]; + std::string cf = tf[3]; + std::string ag = tf[1]; + std::string bg = tf[2]; + std::string cg = tf[3]; + REQUIRE(tf.size() == 3); + REQUIRE(af == "a"); + REQUIRE(bf == "b"); + REQUIRE(cf == "c"); + REQUIRE(tg.size() == 3); + REQUIRE(ag == "a"); + REQUIRE(bg == "b"); + REQUIRE(cg == "c"); +} + +TEST_CASE("containers/table conversions (std::ref)", "test table conversions with as_table and nested, when not directly serializing a temporary / new value") { + sol::state lua; + + std::vector response_words; + response_words.push_back("a"); + response_words.push_back("b"); + response_words.push_back("c"); + auto f = [&response_words]() { return sol::as_table(std::ref(response_words)); }; + auto g = [&response_words]() { return sol::as_nested(std::ref(response_words)); }; + + lua["f"] = std::ref(f); + lua["g"] = std::ref(g); + + sol::safe_function sff = lua["f"]; + sol::safe_function sfg = lua["g"]; + sol::table tf = sff(); + sol::table tg = sfg(); + + std::string af = tf[1]; + std::string bf = tf[2]; + std::string cf = tf[3]; + std::string ag = tf[1]; + std::string bg = tf[2]; + std::string cg = tf[3]; + REQUIRE(tf.size() == 3); + REQUIRE(af == "a"); + REQUIRE(bf == "b"); + REQUIRE(cf == "c"); + REQUIRE(tg.size() == 3); + REQUIRE(ag == "a"); + REQUIRE(bg == "b"); + REQUIRE(cg == "c"); +} + +TEST_CASE("containers/table conversion", "test table conversions with as_table and nested") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.set_function("bark", []() { return sol::as_nested(std::vector{ "bark", "woof" }); }); + + lua.set_function("woof", []() { return sol::as_nested(std::vector{ "bark", "woof" }); }); + + auto result1 = lua.safe_script("v1 = bark()", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto result2 = lua.safe_script("v2 = woof()", sol::script_pass_on_error); + REQUIRE(result2.valid()); + + sol::as_table_t> as_table_strings = lua["v1"]; + sol::nested> nested_strings = lua["v2"]; + + std::vector expected_values{ "bark", "woof" }; + REQUIRE(as_table_strings.source == expected_values); + REQUIRE(nested_strings.source == expected_values); +} + +TEST_CASE("containers/from table argument conversions", "test table conversions without as_table and nested for function args") { + const std::vector expected_values{ "bark", "woof" }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.set_function("f", [&](std::vector t) { return t == expected_values; }); + + auto result0 = lua.safe_script("t = { \"bark\", \"woof\" }"); + REQUIRE(result0.valid()); + + auto result1 = lua.safe_script("assert(f(t))", sol::script_pass_on_error); + REQUIRE(result1.valid()); + + sol::function f = lua["f"]; + sol::table t = lua["t"]; + bool passed = f(t); + REQUIRE(passed); +} + +TEST_CASE("containers/deeply nested", "make sure nested works for deeply-nested C++ containers and works as advertised") { + typedef std::map info_t; + typedef std::vector info_vector; + + class ModList { + public: + info_vector list; + + ModList() { + list.push_back(info_t{ { "a", "b" } }); + } + + sol::nested getList() { + return sol::nested(list); + }; + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype("ModList", "getList", &ModList::getList); + + sol::string_view code = R"( +mods = ModList.new() +local modlist = mods:getList() +print(modlist[1]) +assert(type(modlist) == "table") +assert(type(modlist[1]) == "table") +)"; + + auto result1 = lua.safe_script(code, sol::script_pass_on_error); + REQUIRE(result1.valid()); +} diff --git a/tests/runtime_tests/source/containers.cpp b/tests/runtime_tests/source/containers.cpp index c4d08d88..9b5d8ec7 100644 --- a/tests/runtime_tests/source/containers.cpp +++ b/tests/runtime_tests/source/containers.cpp @@ -22,6 +22,7 @@ // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "sol_test.hpp" +#include "common_classes.hpp" #include @@ -36,128 +37,6 @@ #include #include -class int_shim { -public: - int_shim() = default; - - int_shim(int x) - : x_(x) { - } - - int val() const { - return x_; - } - -private: - int x_ = -1; -}; - -class input_it { -public: - typedef std::input_iterator_tag iterator_category; - typedef int_shim value_type; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef value_type* pointer; - typedef std::ptrdiff_t difference_type; - - input_it() = default; - - input_it(int n, int m) - : n_(n), m_(m), value_(n_) { - assert(n_ >= 0); - assert(m_ >= 0); - assert(n_ <= m_); - - if (!n_ && !m_) { - n_ = -1; - m_ = -1; - value_ = -1; - } - } - - const int_shim& operator*() const { - return value_; - } - - const int_shim* operator->() const { - return &value_; - } - - input_it& operator++() { - assert(n_ >= 0); - assert(m_ >= 0); - if (n_ == m_ - 1) { - n_ = m_ = -1; - } - else { - ++n_; - } - value_ = n_; - return *this; - } - - bool operator==(const input_it& i) const { - return n_ == i.n_ && m_ == i.m_; - } - - bool operator!=(const input_it& i) const { - return !(*this == i); - } - -private: - int n_ = -1; - int m_ = -1; - int_shim value_; -}; - -class not_really_a_container { -public: - using value_type = int_shim; - using iterator = input_it; - using const_iterator = input_it; - - const_iterator begin() const { - return iterator(0, 100); - } - - const_iterator end() const { - return iterator(); - } - - value_type gcc_warning_block() { - return int_shim(); - } - - std::size_t size() const { - return 100; - } -}; - -struct my_vec : public std::vector { - typedef std::vector base_t; - using base_t::base_t; -}; - -namespace sol { - template <> - struct is_container : std::true_type {}; - - template <> - struct container_traits { - static auto begin(lua_State*, my_vec& self) { - return self.begin(); - } - static auto end(lua_State*, my_vec& self) { - return self.end(); - } - static std::ptrdiff_t index_adjustment(lua_State*, my_vec&) { - return 0; - } - }; - -} // namespace sol - auto test_table_return_one() { return sol::as_table(std::vector{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); } @@ -219,171 +98,6 @@ TEST_CASE("containers/returns", "make sure that even references to vectors are b REQUIRE(matching); } -TEST_CASE("containers/table conversions (lvalue)", "test table conversions with as_table and nested, when not directly serializing a temporary / new value") { - sol::state lua; - - auto f = []() { - std::vector response_words; - response_words.push_back("a"); - response_words.push_back("b"); - response_words.push_back("c"); - return sol::as_table(response_words); - }; - auto g = []() { - std::vector response_words; - response_words.push_back("a"); - response_words.push_back("b"); - response_words.push_back("c"); - return sol::as_nested(response_words); - }; - - lua["f"] = std::ref(f); - lua["g"] = std::ref(g); - - sol::safe_function sff = lua["f"]; - sol::safe_function sfg = lua["g"]; - sol::table tf = sff(); - sol::table tg = sfg(); - - std::string af = tf[1]; - std::string bf = tf[2]; - std::string cf = tf[3]; - std::string ag = tf[1]; - std::string bg = tf[2]; - std::string cg = tf[3]; - REQUIRE(tf.size() == 3); - REQUIRE(af == "a"); - REQUIRE(bf == "b"); - REQUIRE(cf == "c"); - REQUIRE(tg.size() == 3); - REQUIRE(ag == "a"); - REQUIRE(bg == "b"); - REQUIRE(cg == "c"); -} - -TEST_CASE("containers/table conversions (std::ref)", "test table conversions with as_table and nested, when not directly serializing a temporary / new value") { - sol::state lua; - - std::vector response_words; - response_words.push_back("a"); - response_words.push_back("b"); - response_words.push_back("c"); - auto f = [&response_words]() { - return sol::as_table(std::ref(response_words)); - }; - auto g = [&response_words]() { - return sol::as_nested(std::ref(response_words)); - }; - - lua["f"] = std::ref(f); - lua["g"] = std::ref(g); - - sol::safe_function sff = lua["f"]; - sol::safe_function sfg = lua["g"]; - sol::table tf = sff(); - sol::table tg = sfg(); - - std::string af = tf[1]; - std::string bf = tf[2]; - std::string cf = tf[3]; - std::string ag = tf[1]; - std::string bg = tf[2]; - std::string cg = tf[3]; - REQUIRE(tf.size() == 3); - REQUIRE(af == "a"); - REQUIRE(bf == "b"); - REQUIRE(cf == "c"); - REQUIRE(tg.size() == 3); - REQUIRE(ag == "a"); - REQUIRE(bg == "b"); - REQUIRE(cg == "c"); -} - -TEST_CASE("containers/table conversion", "test table conversions with as_table and nested") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.set_function("bark", []() { - return sol::as_nested(std::vector{ "bark", "woof" }); - }); - - lua.set_function("woof", []() { - return sol::as_nested(std::vector{ "bark", "woof" }); - }); - - auto result1 = lua.safe_script("v1 = bark()", sol::script_pass_on_error); - REQUIRE(result1.valid()); - auto result2 = lua.safe_script("v2 = woof()", sol::script_pass_on_error); - REQUIRE(result2.valid()); - - sol::as_table_t> as_table_strings = lua["v1"]; - sol::nested> nested_strings = lua["v2"]; - - std::vector expected_values{ "bark", "woof" }; - REQUIRE(as_table_strings.source == expected_values); - REQUIRE(nested_strings.source == expected_values); -} - -TEST_CASE("containers/from table argument conversions", "test table conversions without as_table and nested for function args") { - const std::vector expected_values{ "bark", "woof" }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.set_function("f", [&](std::vector t) { - return t == expected_values; - }); - - auto result0 = lua.safe_script("t = { \"bark\", \"woof\" }"); - REQUIRE(result0.valid()); - - auto result1 = lua.safe_script("assert(f(t))", sol::script_pass_on_error); - REQUIRE(result1.valid()); - - sol::function f = lua["f"]; - sol::table t = lua["t"]; - bool passed = f(t); - REQUIRE(passed); -} - -TEST_CASE("containers/deeply nested", "make sure nested works for deeply-nested C++ containers and works as advertised") { - typedef std::map info_t; - typedef std::vector info_vector; - - class ModList { - public: - info_vector list; - - ModList() { - list.push_back(info_t{ - {"a", "b"} - }); - } - - sol::nested getList () { - return sol::nested(list); - }; - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_usertype("ModList", - "getList", &ModList::getList - ); - - sol::string_view code = R"( -mods = ModList.new() -local modlist = mods:getList() -print(modlist[1]) -assert(type(modlist) == "table") -assert(type(modlist[1]) == "table") -)"; - - auto result1 = lua.safe_script(code, sol::script_pass_on_error); - REQUIRE(result1.valid()); -} - TEST_CASE("containers/vector roundtrip", "make sure vectors can be round-tripped") { sol::state lua; std::vector v{ 1, 2, 3 }; @@ -501,123 +215,6 @@ TEST_CASE("containers/set roundtrip", "make sure sets can be round-tripped") { REQUIRE(areequal); } -TEST_CASE("containers/vector table roundtrip", "make sure vectors can be round-tripped") { - sol::state lua; - std::vector v{ 1, 2, 3 }; - lua.set_function("f", [&]() { - return sol::as_table(v); - }); - auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); - REQUIRE(result1.valid()); - sol::as_table_t> x = lua["x"]; - bool areequal = x.source == v; - REQUIRE(areequal); -} - -TEST_CASE("containers/deque table roundtrip", "make sure deques can be round-tripped") { - sol::state lua; - std::deque v{ 1, 2, 3 }; - lua.set_function("f", [&]() { - return sol::as_table(v); - }); - auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); - REQUIRE(result1.valid()); - sol::as_table_t> x = lua["x"]; - bool areequal = x.source == v; - REQUIRE(areequal); -} - -TEST_CASE("containers/array table roundtrip", "make sure arrays can be round-tripped") { - sol::state lua; - std::array v{ { 1, 2, 3 } }; - lua.set_function("f", [&]() { - return sol::as_table(v); - }); - auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); - REQUIRE(result1.valid()); - sol::as_table_t> x = lua["x"]; - bool areequal = x.source == v; - REQUIRE(areequal); -} - -TEST_CASE("containers/list table roundtrip", "make sure lists can be round-tripped") { - sol::state lua; - std::list v{ 1, 2, 3 }; - lua.set_function("f", [&]() { - return sol::as_table(v); - }); - auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); - REQUIRE(result1.valid()); - sol::as_table_t> x = lua["x"]; - bool areequal = x.source == v; - REQUIRE(areequal); -} - -TEST_CASE("containers/forward_list table roundtrip", "make sure forward_lists can be round-tripped") { - sol::state lua; - std::forward_list v{ 1, 2, 3 }; - lua.set_function("f", [&]() { - return sol::as_table(v); - }); - auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); - REQUIRE(result1.valid()); - sol::as_table_t> x = lua["x"]; - bool areequal = x.source == v; - REQUIRE(areequal); -} - -TEST_CASE("containers/map table roundtrip", "make sure maps can be round-tripped") { - sol::state lua; - std::map v{ { "a", 1 }, { "b", 2 }, { "c", 3 } }; - lua.set_function("f", [&]() { - return sol::as_table(v); - }); - auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); - REQUIRE(result1.valid()); - sol::as_table_t> x = lua["x"]; - bool areequal = x.source == v; - REQUIRE(areequal); -} - -TEST_CASE("containers/unordered_map table roundtrip", "make sure unordered_maps can be round-tripped") { - sol::state lua; - std::unordered_map v{ { "a", 1 }, { "b", 2 }, { "c", 3 } }; - lua.set_function("f", [&]() { - return sol::as_table(v); - }); - auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); - REQUIRE(result1.valid()); - sol::as_table_t> x = lua["x"]; - bool areequal = x.source == v; - REQUIRE(areequal); -} - -TEST_CASE("containers/unordered_set table roundtrip", "make sure unordered_sets can be round-tripped") { - sol::state lua; - std::unordered_set v{ 1, 2, 3 }; - lua.set_function("f", [&]() { - return sol::as_table(v); - }); - auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); - REQUIRE(result1.valid()); - sol::as_table_t> x = lua["x"]; - bool areequal = x.source == v; - REQUIRE(areequal); -} - -TEST_CASE("containers/set table roundtrip", "make sure sets can be round-tripped") { - sol::state lua; - std::set v{ 1, 2, 3 }; - lua.set_function("f", [&]() { - return sol::as_table(v); - }); - auto result1 = lua.safe_script("x = f()", sol::script_pass_on_error); - REQUIRE(result1.valid()); - sol::as_table_t> x = lua["x"]; - bool areequal = x.source == v; - REQUIRE(areequal); -} - TEST_CASE("containers/custom usertype", "make sure container usertype metatables can be overridden") { typedef std::unordered_map bark; @@ -1094,12 +691,6 @@ end } TEST_CASE("containers/non_copyable", "make sure non-copyable types in containers behave properly when stored as a member variable in a bound usertype") { - struct non_copyable { - non_copyable(non_copyable&& other) noexcept = default; - non_copyable& operator=(non_copyable&& other) noexcept = default; - non_copyable(const non_copyable& other) noexcept = delete; - non_copyable& operator=(const non_copyable& other) noexcept = delete; - }; struct test { std::vector b; @@ -1124,33 +715,6 @@ TEST_CASE("containers/non_copyable", "make sure non-copyable types in containers } } -TEST_CASE("containers/input iterators", "test shitty input iterators that are all kinds of B L E H") { - sol::state lua; - lua.open_libraries(sol::lib::base, sol::lib::package); - lua.new_usertype("int_shim", - "new", sol::no_constructor, - "val", &int_shim::val); - - not_really_a_container c; - lua["c"] = &c; -#if SOL_LUA_VERSION > 502 - auto result0 = lua.safe_script(R"lua( -for k, v in pairs(c) do - assert((k - 1) == v:val()) -end -)lua", sol::script_pass_on_error); - REQUIRE(result0.valid()); - -#endif - auto result1 = lua.safe_script(R"lua( -for k=1,#c do - v = c[k] - assert((k - 1) == v:val()) -end -)lua", sol::script_pass_on_error); - REQUIRE(result1.valid()); -} - TEST_CASE("containers/pairs", "test how well pairs work with the underlying system") { typedef std::pair pair_arr_t[5]; typedef int arr_t[5]; @@ -1310,69 +874,3 @@ end check_unordered_values(src, t1ummap.source); } } - -TEST_CASE("containers/custom indexing", "allow containers to set a custom indexing offset") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua["c"] = my_vec{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; - - auto result1 = lua.safe_script("for i=0,9 do assert(i == c[i]) end", sol::script_pass_on_error); - REQUIRE(result1.valid()); - auto result2 = lua.safe_script("assert(c[10] == nil)", sol::script_pass_on_error); - REQUIRE(result2.valid()); - auto result3 = lua.safe_script("assert(c[-1] == nil)", sol::script_pass_on_error); - REQUIRE(result3.valid()); -} - -TEST_CASE("containers/containers of pointers", "containers of pointers shouldn't have their value_type's overly stripped") { - sol::state lua; - - class MyContainer { - public: - typedef int** iterator; - typedef int* value_type; - - std::vector m_vec; - - inline iterator begin() { return m_vec.data(); } - inline iterator end() { return m_vec.data() + m_vec.size(); } - inline void push_back(value_type v) { m_vec.push_back(v); } - }; - int a = 500; - int b = 600; - - MyContainer ctr; - ctr.push_back(&a); - ctr.push_back(&b); - lua["c"] = ctr; - { - auto result1 = lua.safe_script("ap = c[1]", sol::script_pass_on_error); - REQUIRE(result1.valid()); - auto result2 = lua.safe_script("bp = c[2]", sol::script_pass_on_error); - REQUIRE(result2.valid()); - int* ap = lua["ap"]; - int* bp = lua["bp"]; - REQUIRE(ap == &a); - REQUIRE(bp == &b); - REQUIRE(*ap == 500); - REQUIRE(*bp == 600); - } - - std::unordered_map ptrs; - ptrs[5] = &a; - ptrs[6] = &b; - lua["c2"] = ptrs; - { - auto result1 = lua.safe_script("ap = c2[5]", sol::script_pass_on_error); - REQUIRE(result1.valid()); - auto result2 = lua.safe_script("bp = c2[6]", sol::script_pass_on_error); - REQUIRE(result2.valid()); - int* ap = lua["ap"]; - int* bp = lua["bp"]; - REQUIRE(ap == &a); - REQUIRE(bp == &b); - REQUIRE(*ap == 500); - REQUIRE(*bp == 600); - } -} diff --git a/tests/runtime_tests/source/usertype_properties.cpp b/tests/runtime_tests/source/usertype_properties.cpp new file mode 100644 index 00000000..d9b0244f --- /dev/null +++ b/tests/runtime_tests/source/usertype_properties.cpp @@ -0,0 +1,582 @@ +// sol3 + +// The MIT License (MIT) + +// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include "sol_test.hpp" + +#include "common_classes.hpp" + +#include + +bool something_func_true() { + return true; +} + +struct ext_getset { + + int bark = 24; + const int meow = 56; + + ext_getset() = default; + ext_getset(int v) : bark(v) { + } + ext_getset(ext_getset&&) = default; + ext_getset(const ext_getset&) = delete; + ext_getset& operator=(ext_getset&&) = default; + ext_getset& operator=(const ext_getset&) = delete; + ~ext_getset() { + } + + std::string x() { + return "bark bark bark"; + } + + int x2(std::string x) { + return static_cast(x.length()); + } + + void set(sol::variadic_args, sol::this_state, int x) { + bark = x; + } + + int get(sol::this_state, sol::variadic_args) { + return bark; + } + + static void s_set(int) { + } + + static int s_get(int x) { + return x + 20; + } +}; + +template +void des(T& e) { + e.~T(); +} + +template +struct alignas(16) weird_aligned_wrapper { + template + weird_aligned_wrapper(F&& f) : lambda(std::forward(f)) { + } + void operator()(SelfType& self, sol::object param) const { + lambda(self, param.as()); + } + std::function lambda; +}; + +TEST_CASE("usertype/properties", "Check if member properties/variables work") { + struct bark { + int var = 50; + int var2 = 25; + + int get_var2() const { + return var2; + } + + int get_var3() { + return var2; + } + + void set_var2(int x) { + var2 = x; + } + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.new_usertype("bark", + "var", + &bark::var, + "var2", + sol::readonly(&bark::var2), + "a", + sol::property(&bark::get_var2, &bark::set_var2), + "b", + sol::property(&bark::get_var2), + "c", + sol::property(&bark::get_var3), + "d", + sol::property(&bark::set_var2)); + + bark b; + lua.set("b", &b); + + lua.safe_script("b.a = 59"); + lua.safe_script("var2_0 = b.a"); + lua.safe_script("var2_1 = b.b"); + lua.safe_script("b.d = 1568"); + lua.safe_script("var2_2 = b.c"); + + int var2_0 = lua["var2_0"]; + int var2_1 = lua["var2_1"]; + int var2_2 = lua["var2_2"]; + REQUIRE(var2_0 == 59); + REQUIRE(var2_1 == 59); + REQUIRE(var2_2 == 1568); + + { + auto result = lua.safe_script("b.var2 = 24", sol::script_pass_on_error); + REQUIRE_FALSE(result.valid()); + } + { + auto result = lua.safe_script("r = b.d", sol::script_pass_on_error); + REQUIRE_FALSE(result.valid()); + } + { + auto result = lua.safe_script("r = b.d", sol::script_pass_on_error); + REQUIRE_FALSE(result.valid()); + } + { + auto result = lua.safe_script("b.b = 25", sol::script_pass_on_error); + REQUIRE_FALSE(result.valid()); + } + { + auto result = lua.safe_script("b.c = 11", sol::script_pass_on_error); + REQUIRE_FALSE(result.valid()); + } +} + +TEST_CASE("usertype/copyability", "make sure user can write to a class variable even if the class itself isn't copy-safe") { + struct NoCopy { + int get() const { + return _you_can_copy_me; + } + void set(int val) { + _you_can_copy_me = val; + } + + int _you_can_copy_me; + non_copyable _haha_you_cant_copy_me; + }; + + sol::state lua; + lua.new_usertype("NoCopy", "val", sol::property(&NoCopy::get, &NoCopy::set)); + + REQUIRE_NOTHROW(lua.safe_script(R"__( +nocopy = NoCopy.new() +nocopy.val = 5 + )__")); +} + +TEST_CASE("usertype/protect", "users should be allowed to manually protect a function") { + struct protect_me { + int gen(int x) { + return x; + } + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.new_usertype("protect_me", "gen", sol::protect(&protect_me::gen)); + + REQUIRE_NOTHROW(lua.safe_script(R"__( +pm = protect_me.new() +value = pcall(pm.gen,pm) +)__")); + bool value = lua["value"]; + REQUIRE_FALSE(value); +} + +TEST_CASE("usertype/static-properties", "allow for static functions to get and set things as a property") { + static int b = 50; + struct test_t { + static double s_func() { + return b + 0.5; + } + + static void g_func(int v) { + b = v; + } + + std::size_t func() { + return 24; + } + }; + test_t manager; + + sol::state lua; + + lua.new_usertype( + "test", "f", std::function(std::bind(std::mem_fn(&test_t::func), &manager)), "g", sol::property(&test_t::s_func, &test_t::g_func)); + + lua.safe_script("v1 = test.f()"); + lua.safe_script("v2 = test.g"); + lua.safe_script("test.g = 60"); + lua.safe_script("v2a = test.g"); + int v1 = lua["v1"]; + REQUIRE(v1 == 24); + double v2 = lua["v2"]; + REQUIRE(v2 == 50.5); + double v2a = lua["v2a"]; + REQUIRE(v2a == 60.5); +} + +TEST_CASE("usertype/var-and-property", "make sure const vars are readonly and properties can handle lambdas") { + const static int arf = 20; + + struct test { + int value = 10; + }; + + sol::state lua; + lua.open_libraries(); + + lua.new_usertype( + "test", "prop", sol::property([](test& t) { return t.value; }, [](test& t, int x) { t.value = x; }), "global", sol::var(std::ref(arf))); + + lua.safe_script(R"( +t = test.new() +print(t.prop) +t.prop = 50 +print(t.prop) + )"); + + test& t = lua["t"]; + REQUIRE(t.value == 50); + + lua.safe_script(R"( +t = test.new() +print(t.global) + )"); + { + auto result = lua.safe_script("t.global = 20", sol::script_pass_on_error); + REQUIRE_FALSE(result.valid()); + } + lua.safe_script("print(t.global)"); +} + +TEST_CASE("usertype/coverage", "try all the things") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype("ext_getset", + sol::call_constructor, + sol::constructors, sol::types>(), + sol::meta_function::garbage_collect, + sol::destructor(des), + "x", + sol::overload(&ext_getset::x, &ext_getset::x2, [](ext_getset& m, std::string x, int y) { return m.meow + 50 + y + x.length(); }), + "bark", + &ext_getset::bark, + "meow", + &ext_getset::meow, + "readonlybark", + sol::readonly(&ext_getset::bark), + "set", + &ext_getset::set, + "get", + &ext_getset::get, + "sset", + &ext_getset::s_set, + "sget", + &ext_getset::s_get, + "propbark", + sol::property(&ext_getset::set, &ext_getset::get), + "readonlypropbark", + sol::property(&ext_getset::get), + "writeonlypropbark", + sol::property(&ext_getset::set)); + + INFO("usertype created"); + + lua.safe_script(R"( +e = ext_getset() +w = e:x(e:x(), e:x(e:x())) +print(w) +)"); + + int w = lua["w"]; + REQUIRE(w == (56 + 50 + 14 + 14)); + + INFO("REQUIRE(w) successful"); + + lua.safe_script(R"( +e:set(500) +e.sset(24) +x = e:get() +y = e.sget(20) +)"); + + int x = lua["x"]; + int y = lua["y"]; + REQUIRE(x == 500); + REQUIRE(y == 40); + + INFO("REQUIRE(x, y) successful"); + + lua.safe_script(R"( +e.bark = 5001 +a = e:get() +print(e.bark) +print(a) + +e.propbark = 9700 +b = e:get() +print(e.propbark) +print(b) +)"); + int a = lua["a"]; + int b = lua["b"]; + + REQUIRE(a == 5001); + REQUIRE(b == 9700); + + INFO("REQUIRE(a, b) successful"); + + lua.safe_script(R"( +c = e.readonlybark +d = e.meow +print(e.readonlybark) +print(c) +print(e.meow) +print(d) +)"); + + int c = lua["c"]; + int d = lua["d"]; + REQUIRE(c == 9700); + REQUIRE(d == 56); + + INFO("REQUIRE(c, d) successful"); + + lua.safe_script(R"( +e.writeonlypropbark = 500 +z = e.readonlypropbark +print(e.readonlybark) +print(e.bark) +)"); + + int z = lua["z"]; + REQUIRE(z == 500); + + INFO("REQUIRE(z) successful"); + { + auto result = lua.safe_script("e.readonlybark = 24", sol::script_pass_on_error); + REQUIRE_FALSE(result.valid()); + INFO("REQUIRE_FALSE 1 successful"); + } + { + auto result = lua.safe_script("e.readonlypropbark = 500", sol::script_pass_on_error); + REQUIRE_FALSE(result.valid()); + INFO("REQUIRE_FALSE 2 successful"); + } + { + auto result = lua.safe_script("y = e.writeonlypropbark", sol::script_pass_on_error); + REQUIRE_FALSE(result.valid()); + INFO("REQUIRE_FALSE 3 successful"); + } +} + +TEST_CASE("usertype/alignment", "ensure that alignment does not trigger weird aliasing issues") { + struct aligned_base {}; + struct aligned_derived : aligned_base {}; + + sol::state lua; + auto f = [](aligned_base&, float d) { REQUIRE(d == 5.0f); }; + lua.new_usertype("Base", "x", sol::writeonly_property(weird_aligned_wrapper(std::ref(f)))); + lua.new_usertype("Derived", sol::base_classes, sol::bases()); + + aligned_derived d; + lua["d"] = d; + + auto result = lua.safe_script("d.x = 5"); + REQUIRE(result.valid()); +} + +TEST_CASE("usertype/readonly-and-static-functions", "Check if static functions can be called on userdata and from their originating (meta)tables") { + struct bark { + int var = 50; + + void func() { + } + + static void oh_boy() { + } + + static int oh_boy(std::string name) { + return static_cast(name.length()); + } + + int operator()(int x) { + return x; + } + }; + + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.new_usertype("bark", + "var", + &bark::var, + "var2", + sol::readonly(&bark::var), + "something", + something_func_true, + "something2", + [](int x, int y) { return x + y; }, + "func", + &bark::func, + "oh_boy", + sol::overload(sol::resolve(&bark::oh_boy), sol::resolve(&bark::oh_boy)), + sol::meta_function::call_function, + &bark::operator()); + + { + auto result = lua.safe_script("assert(bark.oh_boy('woo') == 3)", sol::script_pass_on_error); + REQUIRE(result.valid()); + } + { + auto result = lua.safe_script("bark.oh_boy()", sol::script_pass_on_error); + REQUIRE(result.valid()); + } + + bark b; + lua.set("b", &b); + + sol::table b_table = lua["b"]; + sol::function member_func = b_table["func"]; + sol::function s = b_table["something"]; + sol::function s2 = b_table["something2"]; + + sol::table b_metatable = b_table[sol::metatable_key]; + bool isvalidmt = b_metatable.valid(); + REQUIRE(isvalidmt); + sol::function b_call = b_metatable["__call"]; + sol::function b_as_function = lua["b"]; + + int x = b_as_function(1); + int y = b_call(b, 1); + bool z = s(); + int w = s2(2, 3); + REQUIRE(x == 1); + REQUIRE(y == 1); + REQUIRE(z); + REQUIRE(w == 5); + + lua.safe_script(R"( +lx = b(1) +ly = getmetatable(b).__call(b, 1) +lz = b.something() +lz2 = bark.something() +lw = b.something2(2, 3) +lw2 = bark.something2(2, 3) + )"); + + int lx = lua["lx"]; + int ly = lua["ly"]; + bool lz = lua["lz"]; + int lw = lua["lw"]; + bool lz2 = lua["lz2"]; + int lw2 = lua["lw2"]; + REQUIRE(lx == 1); + REQUIRE(ly == 1); + REQUIRE(lz); + REQUIRE(lz2); + REQUIRE(lw == 5); + REQUIRE(lw2 == 5); + REQUIRE(lx == ly); + REQUIRE(lz == lz2); + REQUIRE(lw == lw2); + + auto result = lua.safe_script("b.var2 = 2", sol::script_pass_on_error); + REQUIRE_FALSE(result.valid()); +} + +TEST_CASE("usertype/vars", "usertype vars can bind various class items") { + static int muh_variable = 25; + static int through_variable = 10; + + sol::state lua; + lua.open_libraries(); + struct test {}; + lua.new_usertype("test", + "straight", + sol::var(2), + "global", + sol::var(muh_variable), + "ref_global", + sol::var(std::ref(muh_variable)), + "global2", + sol::var(through_variable), + "ref_global2", + sol::var(std::ref(through_variable))); + + int prets = lua["test"]["straight"]; + int pretg = lua["test"]["global"]; + int pretrg = lua["test"]["ref_global"]; + int pretg2 = lua["test"]["global2"]; + int pretrg2 = lua["test"]["ref_global2"]; + + REQUIRE(prets == 2); + REQUIRE(pretg == 25); + REQUIRE(pretrg == 25); + REQUIRE(pretg2 == 10); + REQUIRE(pretrg2 == 10); + + lua.safe_script(R"( +print(test.straight) +test.straight = 50 +print(test.straight) +)"); + int s = lua["test"]["straight"]; + REQUIRE(s == 50); + + lua.safe_script(R"( +t = test.new() +print(t.global) +t.global = 50 +print(t.global) +)"); + int mv = lua["test"]["global"]; + REQUIRE(mv == 50); + REQUIRE(muh_variable == 25); + + lua.safe_script(R"( +print(t.ref_global) +t.ref_global = 50 +print(t.ref_global) +)"); + int rmv = lua["test"]["ref_global"]; + REQUIRE(rmv == 50); + REQUIRE(muh_variable == 50); + + REQUIRE(through_variable == 10); + lua.safe_script(R"( +print(test.global2) +test.global2 = 35 +print(test.global2) +)"); + int tv = lua["test"]["global2"]; + REQUIRE(through_variable == 10); + REQUIRE(tv == 35); + + lua.safe_script(R"( +print(test.ref_global2) +test.ref_global2 = 35 +print(test.ref_global2) +)"); + int rtv = lua["test"]["ref_global2"]; + REQUIRE(rtv == 35); + REQUIRE(through_variable == 35); +} diff --git a/tests/runtime_tests/source/usertype_runtime.cpp b/tests/runtime_tests/source/usertype_runtime.cpp new file mode 100644 index 00000000..3463d237 --- /dev/null +++ b/tests/runtime_tests/source/usertype_runtime.cpp @@ -0,0 +1,341 @@ +// sol3 + +// The MIT License (MIT) + +// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include "sol_test.hpp" + +#include "common_classes.hpp" + +#include + +#include +#include +#include + + +TEST_CASE("usertype/runtime-extensibility", "Check if usertypes are runtime extensible") { + struct thing { + int v = 20; + int func(int a) { + return a; + } + }; + int val = 0; + + class base_a { + public: + int x; + }; + + class derived_b : public base_a {}; + + SECTION("just functions") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype("thing", "func", &thing::func); + + lua.safe_script(R"( +t = thing.new() + )"); + + { + auto result = lua.safe_script(R"( +t.runtime_func = function (a) + return a + 50 +end + )", + sol::script_pass_on_error); + REQUIRE_FALSE(result.valid()); + }; + + { + auto result = lua.safe_script(R"( +function t:runtime_func(a) + return a + 52 +end + )", + sol::script_pass_on_error); + REQUIRE_FALSE(result.valid()); + }; + + lua.safe_script("val = t:func(2)"); + val = lua["val"]; + REQUIRE(val == 2); + + REQUIRE_NOTHROW([&lua]() { + lua.safe_script(R"( +function thing:runtime_func(a) + return a + 1 +end + )"); + }()); + + lua.safe_script("val = t:runtime_func(2)"); + val = lua["val"]; + REQUIRE(val == 3); + } + SECTION("with variable") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype("thing", "func", &thing::func, "v", &thing::v); + + lua.safe_script(R"( +t = thing.new() + )"); + + { + auto result = lua.safe_script(R"( +t.runtime_func = function (a) + return a + 50 +end + )", + sol::script_pass_on_error); + REQUIRE_FALSE(result.valid()); + }; + + { + auto result = lua.safe_script(R"( +function t:runtime_func(a) + return a + 52 +end + )", + sol::script_pass_on_error); + REQUIRE_FALSE(result.valid()); + }; + + lua.safe_script("val = t:func(2)"); + val = lua["val"]; + REQUIRE(val == 2); + + REQUIRE_NOTHROW([&lua]() { + lua.safe_script(R"( +function thing:runtime_func(a) + return a + 1 +end + )"); + }()); + + lua.safe_script("val = t:runtime_func(2)"); + val = lua["val"]; + REQUIRE(val == 3); + } + SECTION("with bases") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype("A", "x", &base_a::x // no crash without this + ); + + lua.new_usertype("B", sol::base_classes, sol::bases()); + + auto pfr0 = lua.safe_script("function A:c() print('A') return 1 end", sol::script_pass_on_error); + REQUIRE(pfr0.valid()); + auto pfr1 = lua.safe_script("function B:c() print('B') return 2 end", sol::script_pass_on_error); + REQUIRE(pfr1.valid()); + auto pfr2 = lua.safe_script("obja = A.new() objb = B.new()", sol::script_default_on_error); + REQUIRE(pfr2.valid()); + auto pfr3 = lua.safe_script("assert(obja:c() == 1)", sol::script_default_on_error); + REQUIRE(pfr3.valid()); + auto pfr4 = lua.safe_script("assert(objb:c() == 2)", sol::script_default_on_error); + REQUIRE(pfr4.valid()); + } +} + +TEST_CASE("usertype/runtime-replacement", "ensure that functions can be properly replaced at runtime for non-indexed things") { + struct heart_base_t {}; + struct heart_t : heart_base_t { + int x = 0; + void func() { + } + }; + + SECTION("plain") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype("a"); + { + auto result1 = lua.safe_script("obj = a.new()", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto result2 = lua.safe_script("function a:heartbeat () print('arf') return 1 end", sol::script_pass_on_error); + REQUIRE(result2.valid()); + auto result3 = lua.safe_script("v1 = obj:heartbeat()", sol::script_pass_on_error); + REQUIRE(result3.valid()); + auto result4 = lua.safe_script("function a:heartbeat () print('bark') return 2 end", sol::script_pass_on_error); + REQUIRE(result4.valid()); + auto result5 = lua.safe_script("v2 = obj:heartbeat()", sol::script_pass_on_error); + REQUIRE(result5.valid()); + auto result6 = lua.safe_script("a.heartbeat = function(self) print('woof') return 3 end", sol::script_pass_on_error); + REQUIRE(result6.valid()); + auto result7 = lua.safe_script("v3 = obj:heartbeat()", sol::script_pass_on_error); + REQUIRE(result7.valid()); + } + int v1 = lua["v1"]; + int v2 = lua["v2"]; + int v3 = lua["v3"]; + REQUIRE(v1 == 1); + REQUIRE(v2 == 2); + REQUIRE(v3 == 3); + } + SECTION("variables") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype("a", "x", &heart_t::x, sol::base_classes, sol::bases()); + + { + auto result1 = lua.safe_script("obj = a.new()", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto result2 = lua.safe_script("function a:heartbeat () print('arf') return 1 end", sol::script_pass_on_error); + REQUIRE(result2.valid()); + auto result3 = lua.safe_script("v1 = obj:heartbeat()", sol::script_pass_on_error); + REQUIRE(result3.valid()); + auto result4 = lua.safe_script("function a:heartbeat () print('bark') return 2 end", sol::script_pass_on_error); + REQUIRE(result4.valid()); + auto result5 = lua.safe_script("v2 = obj:heartbeat()", sol::script_pass_on_error); + REQUIRE(result5.valid()); + auto result6 = lua.safe_script("a.heartbeat = function(self) print('woof') return 3 end", sol::script_pass_on_error); + REQUIRE(result6.valid()); + auto result7 = lua.safe_script("v3 = obj:heartbeat()", sol::script_pass_on_error); + REQUIRE(result7.valid()); + } + int v1 = lua["v1"]; + int v2 = lua["v2"]; + int v3 = lua["v3"]; + REQUIRE(v1 == 1); + REQUIRE(v2 == 2); + REQUIRE(v3 == 3); + } + SECTION("methods") { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype("a", "func", &heart_t::func, sol::base_classes, sol::bases()); + + { + auto result1 = lua.safe_script("obj = a.new()", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto result2 = lua.safe_script("function a:heartbeat () print('arf') return 1 end", sol::script_pass_on_error); + REQUIRE(result2.valid()); + auto result3 = lua.safe_script("v1 = obj:heartbeat()", sol::script_pass_on_error); + REQUIRE(result3.valid()); + auto result4 = lua.safe_script("function a:heartbeat () print('bark') return 2 end", sol::script_pass_on_error); + REQUIRE(result4.valid()); + auto result5 = lua.safe_script("v2 = obj:heartbeat()", sol::script_pass_on_error); + REQUIRE(result5.valid()); + auto result6 = lua.safe_script("a.heartbeat = function(self) print('woof') return 3 end", sol::script_pass_on_error); + REQUIRE(result6.valid()); + auto result7 = lua.safe_script("v3 = obj:heartbeat()", sol::script_pass_on_error); + REQUIRE(result7.valid()); + } + int v1 = lua["v1"]; + int v2 = lua["v2"]; + int v3 = lua["v3"]; + REQUIRE(v1 == 1); + REQUIRE(v2 == 2); + REQUIRE(v3 == 3); + } +} + +TEST_CASE("usertype/runtime additions with newindex", "ensure that additions when new_index is overriden don't hit the specified new_index function") { + class newindex_object {}; + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.new_usertype("object", sol::meta_function::new_index, [](newindex_object&, sol::object, sol::object) { return; }); + + lua["object"]["test"] = [](newindex_object&) { + std::cout << "test" << std::endl; + return 446; + }; + + auto result1 = lua.safe_script("o = object.new()", sol::script_pass_on_error); + REQUIRE(result1.valid()); + auto result2 = lua.safe_script("assert(o:test() == 446)", sol::script_pass_on_error); + REQUIRE(result2.valid()); +} + +TEST_CASE("usertype/meta-key-retrievals", "allow for special meta keys (__index, __newindex) to trigger methods even if overwritten directly") { + SECTION("dynamically") { + static int writes = 0; + static std::string keys[4] = {}; + static int values[4] = {}; + struct d_sample { + void foo(std::string k, int v) { + keys[writes] = k; + values[writes] = v; + ++writes; + } + }; + + sol::state lua; + lua.new_usertype("sample"); + sol::table s = lua["sample"]["new"](); + s[sol::metatable_key][sol::meta_function::new_index] = &d_sample::foo; + lua["var"] = s; + + lua.safe_script("var = sample.new()"); + lua.safe_script("var.key = 2"); + lua.safe_script("var.__newindex = 4"); + lua.safe_script("var.__index = 3"); + lua.safe_script("var.__call = 1"); + REQUIRE(values[0] == 2); + REQUIRE(values[1] == 4); + REQUIRE(values[2] == 3); + REQUIRE(values[3] == 1); + REQUIRE(keys[0] == "key"); + REQUIRE(keys[1] == "__newindex"); + REQUIRE(keys[2] == "__index"); + REQUIRE(keys[3] == "__call"); + } + + SECTION("statically") { + static int writes = 0; + static std::string keys[4] = {}; + static int values[4] = {}; + struct sample { + void foo(std::string k, int v) { + keys[writes] = k; + values[writes] = v; + ++writes; + } + }; + + sol::state lua; + lua.new_usertype("sample", sol::meta_function::new_index, &sample::foo); + + lua.safe_script("var = sample.new()"); + lua.safe_script("var.key = 2"); + lua.safe_script("var.__newindex = 4"); + lua.safe_script("var.__index = 3"); + lua.safe_script("var.__call = 1"); + REQUIRE(values[0] == 2); + REQUIRE(values[1] == 4); + REQUIRE(values[2] == 3); + REQUIRE(values[3] == 1); + REQUIRE(keys[0] == "key"); + REQUIRE(keys[1] == "__newindex"); + REQUIRE(keys[2] == "__index"); + REQUIRE(keys[3] == "__call"); + } +} diff --git a/tests/runtime_tests/source/usertype_unique.cpp b/tests/runtime_tests/source/usertype_unique.cpp new file mode 100644 index 00000000..6be7bde7 --- /dev/null +++ b/tests/runtime_tests/source/usertype_unique.cpp @@ -0,0 +1,160 @@ +// sol3 + +// The MIT License (MIT) + +// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +#include "sol_test.hpp" + +#include "common_classes.hpp" + +#include + + +struct factory_test { +private: + factory_test() { + a = true_a; + } + ~factory_test() { + a = 0; + } + +public: + static int num_saved; + static int num_killed; + + struct deleter { + void operator()(factory_test* f) { + f->~factory_test(); + } + }; + + static const int true_a; + int a; + + static std::unique_ptr make() { + return std::unique_ptr(new factory_test(), deleter()); + } + + static void save(factory_test& f) { + new (&f) factory_test(); + ++num_saved; + } + + static void kill(factory_test& f) { + f.~factory_test(); + ++num_killed; + } +}; + +int factory_test::num_saved = 0; +int factory_test::num_killed = 0; +const int factory_test::true_a = 156; + + +TEST_CASE("usertype/unique-shared-ptr", "manage the conversion and use of unique and shared pointers ('unique usertypes')") { + const int64_t unique_value = 0x7125679355635963; + auto uniqueint = std::make_unique(unique_value); + auto sharedint = std::make_shared(unique_value); + long preusecount = sharedint.use_count(); + { + sol::state lua; + lua.open_libraries(sol::lib::base); + lua.set("uniqueint", std::move(uniqueint)); + lua.set("sharedint", sharedint); + std::unique_ptr& uniqueintref = lua["uniqueint"]; + std::shared_ptr& sharedintref = lua["sharedint"]; + int64_t* rawuniqueintref = lua["uniqueint"]; + int64_t* rawsharedintref = lua["sharedint"]; + int siusecount = sharedintref.use_count(); + REQUIRE((uniqueintref.get() == rawuniqueintref && sharedintref.get() == rawsharedintref)); + REQUIRE((uniqueintref != nullptr && sharedintref != nullptr && rawuniqueintref != nullptr && rawsharedintref != nullptr)); + REQUIRE((unique_value == *uniqueintref.get() && unique_value == *sharedintref.get())); + REQUIRE((unique_value == *rawuniqueintref && unique_value == *rawsharedintref)); + REQUIRE(siusecount == sharedint.use_count()); + std::shared_ptr moreref = sharedint; + REQUIRE(unique_value == *moreref.get()); + REQUIRE(moreref.use_count() == sharedint.use_count()); + REQUIRE(moreref.use_count() == sharedintref.use_count()); + } + REQUIRE(preusecount == sharedint.use_count()); + std::cout << "----- end of 2" << std::endl; +} + +TEST_CASE("usertype/private-constructible", "Check to make sure special snowflake types from Enterprise thingamahjongs work properly.") { + int numsaved = factory_test::num_saved; + int numkilled = factory_test::num_killed; + { + sol::state lua; + lua.open_libraries(sol::lib::base); + + lua.new_usertype( + "factory_test", "new", sol::initializers(factory_test::save), "__gc", sol::destructor(factory_test::kill), "a", &factory_test::a); + + std::unique_ptr f = factory_test::make(); + lua.set("true_a", factory_test::true_a, "f", f.get()); + { + auto result = lua.safe_script("assert(f.a == true_a)", sol::script_pass_on_error); + REQUIRE(result.valid()); + } + + auto code1 + = "local fresh_f = factory_test:new()\n" + "assert(fresh_f.a == true_a)\n"; + auto result1 = lua.safe_script(code1, sol::script_pass_on_error); + REQUIRE(result1.valid()); + } + int expectednumsaved = numsaved + 1; + int expectednumkilled = numkilled + 1; + REQUIRE(expectednumsaved == factory_test::num_saved); + REQUIRE(expectednumkilled == factory_test::num_killed); + std::cout << "----- end of 5" << std::endl; +} + +TEST_CASE("usertype/unique_usertype-check", "make sure unique usertypes don't get pushed as references with function calls and the like") { + class Entity { + public: + std::string GetName() { + return "Charmander"; + } + }; + + sol::state lua; + lua.open_libraries(sol::lib::base, sol::lib::math, sol::lib::string, sol::lib::io); + + lua.new_usertype("Entity", "new", sol::no_constructor, "get_name", &Entity::GetName); + + lua.safe_script(R"( + function my_func(entity) + print("INSIDE LUA") + print(entity:get_name()) + end +)"); + + sol::function my_func = lua["my_func"]; + REQUIRE_NOTHROW([&] { + auto ent = std::make_shared(); + my_func(ent); + Entity ent2; + my_func(ent2); + my_func(std::make_shared()); + }()); +} diff --git a/tests/runtime_tests/source/usertypes.cpp b/tests/runtime_tests/source/usertypes.cpp index 59a37742..4b9f7bae 100644 --- a/tests/runtime_tests/source/usertypes.cpp +++ b/tests/runtime_tests/source/usertypes.cpp @@ -23,190 +23,14 @@ #include "sol_test.hpp" +#include "common_classes.hpp" + #include #include #include #include -struct non_copyable { - non_copyable() = default; - non_copyable(const non_copyable&) = delete; - non_copyable& operator=(const non_copyable&) = delete; - non_copyable(non_copyable&&) = default; - non_copyable& operator=(non_copyable&&) = default; -}; - -struct vars { - vars() { - } - - int boop = 0; - - ~vars() { - } -}; - -struct fuser { - int x; - fuser() - : x(0) { - } - - fuser(int x) - : x(x) { - } - - int add(int y) { - return x + y; - } - - int add2(int y) { - return x + y + 2; - } -}; - -namespace crapola { - struct fuser { - int x; - fuser() - : x(0) { - } - fuser(int x) - : x(x) { - } - fuser(int x, int x2) - : x(x * x2) { - } - - int add(int y) { - return x + y; - } - int add2(int y) { - return x + y + 2; - } - }; -} // namespace crapola - -class Base { -public: - Base(int a_num) - : m_num(a_num) { - } - - int get_num() { - return m_num; - } - -protected: - int m_num; -}; - -class Derived : public Base { -public: - Derived(int a_num) - : Base(a_num) { - } - - int get_num_10() { - return 10 * m_num; - } -}; - -class abstract_A { -public: - virtual void a() = 0; -}; - -class abstract_B : public abstract_A { -public: - virtual void a() override { - INFO("overridden a() in B : public A - BARK"); - } -}; - -struct Vec { - float x, y, z; - Vec(float x, float y, float z) - : x{ x }, y{ y }, z{ z } { - } - float length() { - return sqrtf(x * x + y * y + z * z); - } - Vec normalized() { - float invS = 1 / length(); - return { x * invS, y * invS, z * invS }; - } -}; - -struct giver { - int a = 0; - - giver() { - } - - void gief() { - a = 1; - } - - static int stuff() { - std::cout << "stuff" << std::endl; - return 97; - } - - static void gief_stuff(giver& t, int a) { - t.a = a; - } - - ~giver() { - } -}; - -struct factory_test { -private: - factory_test() { - a = true_a; - } - ~factory_test() { - a = 0; - } - -public: - static int num_saved; - static int num_killed; - - struct deleter { - void operator()(factory_test* f) { - f->~factory_test(); - } - }; - - static const int true_a; - int a; - - static std::unique_ptr make() { - return std::unique_ptr(new factory_test(), deleter()); - } - - static void save(factory_test& f) { - new (&f) factory_test(); - ++num_saved; - } - - static void kill(factory_test& f) { - f.~factory_test(); - ++num_killed; - } -}; - -int factory_test::num_saved = 0; -int factory_test::num_killed = 0; -const int factory_test::true_a = 156; - -bool something() { - return true; -} - struct thing { int v = 100; @@ -238,51 +62,6 @@ struct self_test { } }; -struct ext_getset { - - int bark = 24; - const int meow = 56; - - ext_getset() = default; - ext_getset(int v) - : bark(v) { - } - ext_getset(ext_getset&&) = default; - ext_getset(const ext_getset&) = delete; - ext_getset& operator=(ext_getset&&) = default; - ext_getset& operator=(const ext_getset&) = delete; - ~ext_getset() { - } - - std::string x() { - return "bark bark bark"; - } - - int x2(std::string x) { - return static_cast(x.length()); - } - - void set(sol::variadic_args, sol::this_state, int x) { - bark = x; - } - - int get(sol::this_state, sol::variadic_args) { - return bark; - } - - static void s_set(int) { - } - - static int s_get(int x) { - return x + 20; - } -}; - -template -void des(T& e) { - e.~T(); -} - struct matrix_xf { float a, b; @@ -304,17 +83,6 @@ struct matrix_xi { return m; } }; -template -struct alignas(16) weird_aligned_wrapper { - template - weird_aligned_wrapper(F&& f) - : lambda(std::forward(f)) { - } - void operator()(SelfType& self, sol::object param) const { - lambda(self, param.as()); - } - std::function lambda; -}; TEST_CASE("usertype/usertype", "Show that we can create classes from usertype and use them") { sol::state lua; @@ -657,35 +425,6 @@ TEST_CASE("usertype/nonmember-functions", "let users set non-member functions th std::cout << "----- end of 1" << std::endl; } -TEST_CASE("usertype/unique-shared-ptr", "manage the conversion and use of unique and shared pointers ('unique usertypes')") { - const int64_t unique_value = 0x7125679355635963; - auto uniqueint = std::make_unique(unique_value); - auto sharedint = std::make_shared(unique_value); - long preusecount = sharedint.use_count(); - { - sol::state lua; - lua.open_libraries(sol::lib::base); - lua.set("uniqueint", std::move(uniqueint)); - lua.set("sharedint", sharedint); - std::unique_ptr& uniqueintref = lua["uniqueint"]; - std::shared_ptr& sharedintref = lua["sharedint"]; - int64_t* rawuniqueintref = lua["uniqueint"]; - int64_t* rawsharedintref = lua["sharedint"]; - int siusecount = sharedintref.use_count(); - REQUIRE((uniqueintref.get() == rawuniqueintref && sharedintref.get() == rawsharedintref)); - REQUIRE((uniqueintref != nullptr && sharedintref != nullptr && rawuniqueintref != nullptr && rawsharedintref != nullptr)); - REQUIRE((unique_value == *uniqueintref.get() && unique_value == *sharedintref.get())); - REQUIRE((unique_value == *rawuniqueintref && unique_value == *rawsharedintref)); - REQUIRE(siusecount == sharedint.use_count()); - std::shared_ptr moreref = sharedint; - REQUIRE(unique_value == *moreref.get()); - REQUIRE(moreref.use_count() == sharedint.use_count()); - REQUIRE(moreref.use_count() == sharedintref.use_count()); - } - REQUIRE(preusecount == sharedint.use_count()); - std::cout << "----- end of 2" << std::endl; -} - TEST_CASE("regressions/one", "issue number 48") { sol::state lua; lua.new_usertype("vars", @@ -740,38 +479,6 @@ TEST_CASE("usertype/get-set-references", "properly get and set with std::ref sem std::cout << "----- end of 4" << std::endl; } -TEST_CASE("usertype/private-constructible", "Check to make sure special snowflake types from Enterprise thingamahjongs work properly.") { - int numsaved = factory_test::num_saved; - int numkilled = factory_test::num_killed; - { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_usertype("factory_test", - "new", sol::initializers(factory_test::save), - "__gc", sol::destructor(factory_test::kill), - "a", &factory_test::a); - - std::unique_ptr f = factory_test::make(); - lua.set("true_a", factory_test::true_a, "f", f.get()); - { - auto result = lua.safe_script("assert(f.a == true_a)", sol::script_pass_on_error); - REQUIRE(result.valid()); - } - - auto code1 = - "local fresh_f = factory_test:new()\n" - "assert(fresh_f.a == true_a)\n"; - auto result1 = lua.safe_script(code1, sol::script_pass_on_error); - REQUIRE(result1.valid()); - } - int expectednumsaved = numsaved + 1; - int expectednumkilled = numkilled + 1; - REQUIRE(expectednumsaved == factory_test::num_saved); - REQUIRE(expectednumkilled == factory_test::num_killed); - std::cout << "----- end of 5" << std::endl; -} - TEST_CASE("usertype/const-pointer", "Make sure const pointers can be taken") { struct A_x { int x = 201; @@ -921,163 +628,6 @@ TEST_CASE("usertype/reference-and-constness", "Make sure constness compiles prop } } -TEST_CASE("usertype/readonly-and-static-functions", "Check if static functions can be called on userdata and from their originating (meta)tables") { - struct bark { - int var = 50; - - void func() { - } - - static void oh_boy() { - } - - static int oh_boy(std::string name) { - return static_cast(name.length()); - } - - int operator()(int x) { - return x; - } - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - lua.new_usertype("bark", - "var", &bark::var, - "var2", sol::readonly(&bark::var), - "something", something, - "something2", [](int x, int y) { return x + y; }, - "func", &bark::func, - "oh_boy", sol::overload(sol::resolve(&bark::oh_boy), sol::resolve(&bark::oh_boy)), - sol::meta_function::call_function, &bark::operator()); - - { - auto result = lua.safe_script("assert(bark.oh_boy('woo') == 3)", sol::script_pass_on_error); - REQUIRE(result.valid()); - } - { - auto result = lua.safe_script("bark.oh_boy()", sol::script_pass_on_error); - REQUIRE(result.valid()); - } - - bark b; - lua.set("b", &b); - - sol::table b_table = lua["b"]; - sol::function member_func = b_table["func"]; - sol::function s = b_table["something"]; - sol::function s2 = b_table["something2"]; - - sol::table b_metatable = b_table[sol::metatable_key]; - bool isvalidmt = b_metatable.valid(); - REQUIRE(isvalidmt); - sol::function b_call = b_metatable["__call"]; - sol::function b_as_function = lua["b"]; - - int x = b_as_function(1); - int y = b_call(b, 1); - bool z = s(); - int w = s2(2, 3); - REQUIRE(x == 1); - REQUIRE(y == 1); - REQUIRE(z); - REQUIRE(w == 5); - - lua.safe_script(R"( -lx = b(1) -ly = getmetatable(b).__call(b, 1) -lz = b.something() -lz2 = bark.something() -lw = b.something2(2, 3) -lw2 = bark.something2(2, 3) - )"); - - int lx = lua["lx"]; - int ly = lua["ly"]; - bool lz = lua["lz"]; - int lw = lua["lw"]; - bool lz2 = lua["lz2"]; - int lw2 = lua["lw2"]; - REQUIRE(lx == 1); - REQUIRE(ly == 1); - REQUIRE(lz); - REQUIRE(lz2); - REQUIRE(lw == 5); - REQUIRE(lw2 == 5); - REQUIRE(lx == ly); - REQUIRE(lz == lz2); - REQUIRE(lw == lw2); - - auto result = lua.safe_script("b.var2 = 2", sol::script_pass_on_error); - REQUIRE_FALSE(result.valid()); -} - -TEST_CASE("usertype/properties", "Check if member properties/variables work") { - struct bark { - int var = 50; - int var2 = 25; - - int get_var2() const { - return var2; - } - - int get_var3() { - return var2; - } - - void set_var2(int x) { - var2 = x; - } - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - lua.new_usertype("bark", - "var", &bark::var, - "var2", sol::readonly(&bark::var2), - "a", sol::property(&bark::get_var2, &bark::set_var2), - "b", sol::property(&bark::get_var2), - "c", sol::property(&bark::get_var3), - "d", sol::property(&bark::set_var2)); - - bark b; - lua.set("b", &b); - - lua.safe_script("b.a = 59"); - lua.safe_script("var2_0 = b.a"); - lua.safe_script("var2_1 = b.b"); - lua.safe_script("b.d = 1568"); - lua.safe_script("var2_2 = b.c"); - - int var2_0 = lua["var2_0"]; - int var2_1 = lua["var2_1"]; - int var2_2 = lua["var2_2"]; - REQUIRE(var2_0 == 59); - REQUIRE(var2_1 == 59); - REQUIRE(var2_2 == 1568); - - { - auto result = lua.safe_script("b.var2 = 24", sol::script_pass_on_error); - REQUIRE_FALSE(result.valid()); - } - { - auto result = lua.safe_script("r = b.d", sol::script_pass_on_error); - REQUIRE_FALSE(result.valid()); - } - { - auto result = lua.safe_script("r = b.d", sol::script_pass_on_error); - REQUIRE_FALSE(result.valid()); - } - { - auto result = lua.safe_script("b.b = 25", sol::script_pass_on_error); - REQUIRE_FALSE(result.valid()); - } - { - auto result = lua.safe_script("b.c = 11", sol::script_pass_on_error); - REQUIRE_FALSE(result.valid()); - } -} - TEST_CASE("usertype/safety", "crash with an exception -- not a segfault -- on bad userdata calls") { class Test { public: @@ -1181,7 +731,6 @@ TEST_CASE("usertype/blank_constructor", "make sure lua types cannot be construct } TEST_CASE("usertype/no_constructor", "make sure lua types cannot be constructed if a blank / empty constructor is provided") { - SECTION("order1") { sol::state lua; lua.open_libraries(sol::lib::base); @@ -1224,327 +773,6 @@ TEST_CASE("usertype/no_constructor", "make sure lua types cannot be constructed } } -TEST_CASE("usertype/coverage", "try all the things") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_usertype("ext_getset", - sol::call_constructor, sol::constructors, sol::types>(), - sol::meta_function::garbage_collect, sol::destructor(des), - "x", sol::overload(&ext_getset::x, &ext_getset::x2, [](ext_getset& m, std::string x, int y) { - return m.meow + 50 + y + x.length(); - }), - "bark", &ext_getset::bark, "meow", &ext_getset::meow, "readonlybark", sol::readonly(&ext_getset::bark), "set", &ext_getset::set, "get", &ext_getset::get, "sset", &ext_getset::s_set, "sget", &ext_getset::s_get, "propbark", sol::property(&ext_getset::set, &ext_getset::get), "readonlypropbark", sol::property(&ext_getset::get), "writeonlypropbark", sol::property(&ext_getset::set)); - - INFO("usertype created"); - - lua.safe_script(R"( -e = ext_getset() -w = e:x(e:x(), e:x(e:x())) -print(w) -)"); - - int w = lua["w"]; - REQUIRE(w == (56 + 50 + 14 + 14)); - - INFO("REQUIRE(w) successful"); - - lua.safe_script(R"( -e:set(500) -e.sset(24) -x = e:get() -y = e.sget(20) -)"); - - int x = lua["x"]; - int y = lua["y"]; - REQUIRE(x == 500); - REQUIRE(y == 40); - - INFO("REQUIRE(x, y) successful"); - - lua.safe_script(R"( -e.bark = 5001 -a = e:get() -print(e.bark) -print(a) - -e.propbark = 9700 -b = e:get() -print(e.propbark) -print(b) -)"); - int a = lua["a"]; - int b = lua["b"]; - - REQUIRE(a == 5001); - REQUIRE(b == 9700); - - INFO("REQUIRE(a, b) successful"); - - lua.safe_script(R"( -c = e.readonlybark -d = e.meow -print(e.readonlybark) -print(c) -print(e.meow) -print(d) -)"); - - int c = lua["c"]; - int d = lua["d"]; - REQUIRE(c == 9700); - REQUIRE(d == 56); - - INFO("REQUIRE(c, d) successful"); - - lua.safe_script(R"( -e.writeonlypropbark = 500 -z = e.readonlypropbark -print(e.readonlybark) -print(e.bark) -)"); - - int z = lua["z"]; - REQUIRE(z == 500); - - INFO("REQUIRE(z) successful"); - { - auto result = lua.safe_script("e.readonlybark = 24", sol::script_pass_on_error); - REQUIRE_FALSE(result.valid()); - INFO("REQUIRE_FALSE 1 successful"); - } - { - auto result = lua.safe_script("e.readonlypropbark = 500", sol::script_pass_on_error); - REQUIRE_FALSE(result.valid()); - INFO("REQUIRE_FALSE 2 successful"); - } - { - auto result = lua.safe_script("y = e.writeonlypropbark", sol::script_pass_on_error); - REQUIRE_FALSE(result.valid()); - INFO("REQUIRE_FALSE 3 successful"); - } -} - -TEST_CASE("usertype/copyability", "make sure user can write to a class variable even if the class itself isn't copy-safe") { - struct NoCopy { - int get() const { - return _you_can_copy_me; - } - void set(int val) { - _you_can_copy_me = val; - } - - int _you_can_copy_me; - non_copyable _haha_you_cant_copy_me; - }; - - sol::state lua; - lua.new_usertype("NoCopy", "val", sol::property(&NoCopy::get, &NoCopy::set)); - - REQUIRE_NOTHROW( - lua.safe_script(R"__( -nocopy = NoCopy.new() -nocopy.val = 5 - )__")); -} - -TEST_CASE("usertype/protect", "users should be allowed to manually protect a function") { - struct protect_me { - int gen(int x) { - return x; - } - }; - - sol::state lua; - lua.open_libraries(sol::lib::base); - lua.new_usertype("protect_me", - "gen", sol::protect(&protect_me::gen)); - - REQUIRE_NOTHROW( - lua.safe_script(R"__( -pm = protect_me.new() -value = pcall(pm.gen,pm) -)__")); - bool value = lua["value"]; - REQUIRE_FALSE(value); -} - -TEST_CASE("usertype/vars", "usertype vars can bind various class items") { - static int muh_variable = 25; - static int through_variable = 10; - - sol::state lua; - lua.open_libraries(); - struct test {}; - lua.new_usertype("test", - "straight", sol::var(2), - "global", sol::var(muh_variable), - "ref_global", sol::var(std::ref(muh_variable)), - "global2", sol::var(through_variable), - "ref_global2", sol::var(std::ref(through_variable))); - - int prets = lua["test"]["straight"]; - int pretg = lua["test"]["global"]; - int pretrg = lua["test"]["ref_global"]; - int pretg2 = lua["test"]["global2"]; - int pretrg2 = lua["test"]["ref_global2"]; - - REQUIRE(prets == 2); - REQUIRE(pretg == 25); - REQUIRE(pretrg == 25); - REQUIRE(pretg2 == 10); - REQUIRE(pretrg2 == 10); - - lua.safe_script(R"( -print(test.straight) -test.straight = 50 -print(test.straight) -)"); - int s = lua["test"]["straight"]; - REQUIRE(s == 50); - - lua.safe_script(R"( -t = test.new() -print(t.global) -t.global = 50 -print(t.global) -)"); - int mv = lua["test"]["global"]; - REQUIRE(mv == 50); - REQUIRE(muh_variable == 25); - - lua.safe_script(R"( -print(t.ref_global) -t.ref_global = 50 -print(t.ref_global) -)"); - int rmv = lua["test"]["ref_global"]; - REQUIRE(rmv == 50); - REQUIRE(muh_variable == 50); - - REQUIRE(through_variable == 10); - lua.safe_script(R"( -print(test.global2) -test.global2 = 35 -print(test.global2) -)"); - int tv = lua["test"]["global2"]; - REQUIRE(through_variable == 10); - REQUIRE(tv == 35); - - lua.safe_script(R"( -print(test.ref_global2) -test.ref_global2 = 35 -print(test.ref_global2) -)"); - int rtv = lua["test"]["ref_global2"]; - REQUIRE(rtv == 35); - REQUIRE(through_variable == 35); -} - -TEST_CASE("usertype/static-properties", "allow for static functions to get and set things as a property") { - static int b = 50; - struct test_t { - static double s_func() { - return b + 0.5; - } - - static void g_func(int v) { - b = v; - } - - std::size_t func() { - return 24; - } - }; - test_t manager; - - sol::state lua; - - lua.new_usertype("test", - "f", std::function(std::bind(std::mem_fn(&test_t::func), &manager)), - "g", sol::property(&test_t::s_func, &test_t::g_func)); - - lua.safe_script("v1 = test.f()"); - lua.safe_script("v2 = test.g"); - lua.safe_script("test.g = 60"); - lua.safe_script("v2a = test.g"); - int v1 = lua["v1"]; - REQUIRE(v1 == 24); - double v2 = lua["v2"]; - REQUIRE(v2 == 50.5); - double v2a = lua["v2a"]; - REQUIRE(v2a == 60.5); -} - -TEST_CASE("usertype/var-and-property", "make sure const vars are readonly and properties can handle lambdas") { - const static int arf = 20; - - struct test { - int value = 10; - }; - - sol::state lua; - lua.open_libraries(); - - lua.new_usertype("test", - "prop", sol::property([](test& t) { return t.value; }, [](test& t, int x) { t.value = x; }), - "global", sol::var(std::ref(arf))); - - lua.safe_script(R"( -t = test.new() -print(t.prop) -t.prop = 50 -print(t.prop) - )"); - - test& t = lua["t"]; - REQUIRE(t.value == 50); - - lua.safe_script(R"( -t = test.new() -print(t.global) - )"); - { - auto result = lua.safe_script("t.global = 20", sol::script_pass_on_error); - REQUIRE_FALSE(result.valid()); - } - lua.safe_script("print(t.global)"); -} - -TEST_CASE("usertype/unique_usertype-check", "make sure unique usertypes don't get pushed as references with function calls and the like") { - class Entity { - public: - std::string GetName() { - return "Charmander"; - } - }; - - sol::state lua; - lua.open_libraries(sol::lib::base, sol::lib::math, sol::lib::string, sol::lib::io); - - lua.new_usertype("Entity", - "new", sol::no_constructor, - "get_name", &Entity::GetName); - - lua.safe_script(R"( - function my_func(entity) - print("INSIDE LUA") - print(entity:get_name()) - end -)"); - - sol::function my_func = lua["my_func"]; - REQUIRE_NOTHROW([&] { - auto ent = std::make_shared(); - my_func(ent); - Entity ent2; - my_func(ent2); - my_func(std::make_shared()); - }()); -} - TEST_CASE("usertype/abstract-base-class", "Ensure that abstract base classes and such can be registered") { sol::state lua; lua.new_usertype("A", "a", &abstract_A::a); @@ -1615,343 +843,6 @@ TEST_CASE("usertype/missing-key", "make sure a missing key returns nil") { REQUIRE(isnil); } -TEST_CASE("usertype/runtime-extensibility", "Check if usertypes are runtime extensible") { - struct thing { - int v = 20; - int func(int a) { - return a; - } - }; - int val = 0; - - class base_a { - public: - int x; - }; - - class derived_b : public base_a { - }; - - SECTION("just functions") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_usertype("thing", - "func", &thing::func); - - lua.safe_script(R"( -t = thing.new() - )"); - - { - auto result = lua.safe_script(R"( -t.runtime_func = function (a) - return a + 50 -end - )", - sol::script_pass_on_error); - REQUIRE_FALSE(result.valid()); - }; - - { - auto result = lua.safe_script(R"( -function t:runtime_func(a) - return a + 52 -end - )", - sol::script_pass_on_error); - REQUIRE_FALSE(result.valid()); - }; - - lua.safe_script("val = t:func(2)"); - val = lua["val"]; - REQUIRE(val == 2); - - REQUIRE_NOTHROW([&lua]() { - lua.safe_script(R"( -function thing:runtime_func(a) - return a + 1 -end - )"); - }()); - - lua.safe_script("val = t:runtime_func(2)"); - val = lua["val"]; - REQUIRE(val == 3); - } - SECTION("with variable") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_usertype("thing", - "func", &thing::func, - "v", &thing::v); - - lua.safe_script(R"( -t = thing.new() - )"); - - { - auto result = lua.safe_script(R"( -t.runtime_func = function (a) - return a + 50 -end - )", - sol::script_pass_on_error); - REQUIRE_FALSE(result.valid()); - }; - - { - auto result = lua.safe_script(R"( -function t:runtime_func(a) - return a + 52 -end - )", - sol::script_pass_on_error); - REQUIRE_FALSE(result.valid()); - }; - - lua.safe_script("val = t:func(2)"); - val = lua["val"]; - REQUIRE(val == 2); - - REQUIRE_NOTHROW([&lua]() { - lua.safe_script(R"( -function thing:runtime_func(a) - return a + 1 -end - )"); - }()); - - lua.safe_script("val = t:runtime_func(2)"); - val = lua["val"]; - REQUIRE(val == 3); - } - SECTION("with bases") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_usertype("A", - "x", &base_a::x //no crash without this - ); - - lua.new_usertype("B", - sol::base_classes, sol::bases()); - - auto pfr0 = lua.safe_script("function A:c() print('A') return 1 end", sol::script_pass_on_error); - REQUIRE(pfr0.valid()); - auto pfr1 = lua.safe_script("function B:c() print('B') return 2 end", sol::script_pass_on_error); - REQUIRE(pfr1.valid()); - auto pfr2 = lua.safe_script("obja = A.new() objb = B.new()", sol::script_default_on_error); - REQUIRE(pfr2.valid()); - auto pfr3 = lua.safe_script("assert(obja:c() == 1)", sol::script_default_on_error); - REQUIRE(pfr3.valid()); - auto pfr4 = lua.safe_script("assert(objb:c() == 2)", sol::script_default_on_error); - REQUIRE(pfr4.valid()); - } -} - -TEST_CASE("usertype/runtime-replacement", "ensure that functions can be properly replaced at runtime for non-indexed things") { - struct heart_base_t {}; - struct heart_t : heart_base_t { - int x = 0; - void func() { - } - }; - - SECTION("plain") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_usertype("a"); - { - auto result1 = lua.safe_script("obj = a.new()", sol::script_pass_on_error); - REQUIRE(result1.valid()); - auto result2 = lua.safe_script("function a:heartbeat () print('arf') return 1 end", sol::script_pass_on_error); - REQUIRE(result2.valid()); - auto result3 = lua.safe_script("v1 = obj:heartbeat()", sol::script_pass_on_error); - REQUIRE(result3.valid()); - auto result4 = lua.safe_script("function a:heartbeat () print('bark') return 2 end", sol::script_pass_on_error); - REQUIRE(result4.valid()); - auto result5 = lua.safe_script("v2 = obj:heartbeat()", sol::script_pass_on_error); - REQUIRE(result5.valid()); - auto result6 = lua.safe_script("a.heartbeat = function(self) print('woof') return 3 end", sol::script_pass_on_error); - REQUIRE(result6.valid()); - auto result7 = lua.safe_script("v3 = obj:heartbeat()", sol::script_pass_on_error); - REQUIRE(result7.valid()); - } - int v1 = lua["v1"]; - int v2 = lua["v2"]; - int v3 = lua["v3"]; - REQUIRE(v1 == 1); - REQUIRE(v2 == 2); - REQUIRE(v3 == 3); - } - SECTION("variables") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_usertype("a", "x", &heart_t::x, sol::base_classes, sol::bases()); - - { - auto result1 = lua.safe_script("obj = a.new()", sol::script_pass_on_error); - REQUIRE(result1.valid()); - auto result2 = lua.safe_script("function a:heartbeat () print('arf') return 1 end", sol::script_pass_on_error); - REQUIRE(result2.valid()); - auto result3 = lua.safe_script("v1 = obj:heartbeat()", sol::script_pass_on_error); - REQUIRE(result3.valid()); - auto result4 = lua.safe_script("function a:heartbeat () print('bark') return 2 end", sol::script_pass_on_error); - REQUIRE(result4.valid()); - auto result5 = lua.safe_script("v2 = obj:heartbeat()", sol::script_pass_on_error); - REQUIRE(result5.valid()); - auto result6 = lua.safe_script("a.heartbeat = function(self) print('woof') return 3 end", sol::script_pass_on_error); - REQUIRE(result6.valid()); - auto result7 = lua.safe_script("v3 = obj:heartbeat()", sol::script_pass_on_error); - REQUIRE(result7.valid()); - } - int v1 = lua["v1"]; - int v2 = lua["v2"]; - int v3 = lua["v3"]; - REQUIRE(v1 == 1); - REQUIRE(v2 == 2); - REQUIRE(v3 == 3); - } - SECTION("methods") { - sol::state lua; - lua.open_libraries(sol::lib::base); - - lua.new_usertype("a", "func", &heart_t::func, sol::base_classes, sol::bases()); - - { - auto result1 = lua.safe_script("obj = a.new()", sol::script_pass_on_error); - REQUIRE(result1.valid()); - auto result2 = lua.safe_script("function a:heartbeat () print('arf') return 1 end", sol::script_pass_on_error); - REQUIRE(result2.valid()); - auto result3 = lua.safe_script("v1 = obj:heartbeat()", sol::script_pass_on_error); - REQUIRE(result3.valid()); - auto result4 = lua.safe_script("function a:heartbeat () print('bark') return 2 end", sol::script_pass_on_error); - REQUIRE(result4.valid()); - auto result5 = lua.safe_script("v2 = obj:heartbeat()", sol::script_pass_on_error); - REQUIRE(result5.valid()); - auto result6 = lua.safe_script("a.heartbeat = function(self) print('woof') return 3 end", sol::script_pass_on_error); - REQUIRE(result6.valid()); - auto result7 = lua.safe_script("v3 = obj:heartbeat()", sol::script_pass_on_error); - REQUIRE(result7.valid()); - } - int v1 = lua["v1"]; - int v2 = lua["v2"]; - int v3 = lua["v3"]; - REQUIRE(v1 == 1); - REQUIRE(v2 == 2); - REQUIRE(v3 == 3); - } -} - -TEST_CASE("usertype/runtime additions with newindex", "ensure that additions when new_index is overriden don't hit the specified new_index function") { - class newindex_object {}; - sol::state lua; - lua.open_libraries(sol::lib::base); - lua.new_usertype("object", - sol::meta_function::new_index, [](newindex_object&, sol::object, sol::object) { - return; - }); - - lua["object"]["test"] = [](newindex_object&) { - std::cout << "test" << std::endl; - return 446; - }; - - auto result1 = lua.safe_script("o = object.new()", sol::script_pass_on_error); - REQUIRE(result1.valid()); - auto result2 = lua.safe_script("assert(o:test() == 446)", sol::script_pass_on_error); - REQUIRE(result2.valid()); -} - -TEST_CASE("usertype/alignment", "ensure that alignment does not trigger weird aliasing issues") { - struct aligned_base {}; - struct aligned_derived : aligned_base {}; - - sol::state lua; - auto f = [](aligned_base&, float d) { - REQUIRE(d == 5.0f); - }; - lua.new_usertype("Base", - "x", sol::writeonly_property(weird_aligned_wrapper(std::ref(f)))); - lua.new_usertype("Derived", - sol::base_classes, sol::bases()); - - aligned_derived d; - lua["d"] = d; - - auto result = lua.safe_script("d.x = 5"); - REQUIRE(result.valid()); -} - -TEST_CASE("usertype/meta-key-retrievals", "allow for special meta keys (__index, __newindex) to trigger methods even if overwritten directly") { - SECTION("dynamically") { - static int writes = 0; - static std::string keys[4] = {}; - static int values[4] = {}; - struct d_sample { - void foo(std::string k, int v) { - keys[writes] = k; - values[writes] = v; - ++writes; - } - }; - - sol::state lua; - lua.new_usertype("sample"); - sol::table s = lua["sample"]["new"](); - s[sol::metatable_key][sol::meta_function::new_index] = &d_sample::foo; - lua["var"] = s; - - lua.safe_script("var = sample.new()"); - lua.safe_script("var.key = 2"); - lua.safe_script("var.__newindex = 4"); - lua.safe_script("var.__index = 3"); - lua.safe_script("var.__call = 1"); - REQUIRE(values[0] == 2); - REQUIRE(values[1] == 4); - REQUIRE(values[2] == 3); - REQUIRE(values[3] == 1); - REQUIRE(keys[0] == "key"); - REQUIRE(keys[1] == "__newindex"); - REQUIRE(keys[2] == "__index"); - REQUIRE(keys[3] == "__call"); - } - - SECTION("statically") { - static int writes = 0; - static std::string keys[4] = {}; - static int values[4] = {}; - struct sample { - void foo(std::string k, int v) { - keys[writes] = k; - values[writes] = v; - ++writes; - } - }; - - sol::state lua; - lua.new_usertype("sample", sol::meta_function::new_index, &sample::foo); - - lua.safe_script("var = sample.new()"); - lua.safe_script("var.key = 2"); - lua.safe_script("var.__newindex = 4"); - lua.safe_script("var.__index = 3"); - lua.safe_script("var.__call = 1"); - REQUIRE(values[0] == 2); - REQUIRE(values[1] == 4); - REQUIRE(values[2] == 3); - REQUIRE(values[3] == 1); - REQUIRE(keys[0] == "key"); - REQUIRE(keys[1] == "__newindex"); - REQUIRE(keys[2] == "__index"); - REQUIRE(keys[3] == "__call"); - } -} - TEST_CASE("usertype/basic type information", "check that we can query some basic type information") { struct my_thing {};