mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
258 lines
6.0 KiB
C++
258 lines
6.0 KiB
C++
|
// 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 <catch.hpp>
|
||
|
|
||
|
#include <iterator>
|
||
|
#include <vector>
|
||
|
#include <list>
|
||
|
#include <forward_list>
|
||
|
#include <map>
|
||
|
#include <deque>
|
||
|
#include <array>
|
||
|
#include <unordered_map>
|
||
|
#include <set>
|
||
|
#include <unordered_set>
|
||
|
|
||
|
|
||
|
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<int> {
|
||
|
typedef std::vector<int> base_t;
|
||
|
using base_t::base_t;
|
||
|
};
|
||
|
|
||
|
namespace sol {
|
||
|
template <>
|
||
|
struct is_container<my_vec> : std::true_type {};
|
||
|
|
||
|
template <>
|
||
|
struct container_traits<my_vec> {
|
||
|
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>("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<value_type> 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<int, int*> 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);
|
||
|
}
|
||
|
}
|