mirror of
https://github.com/ThePhD/sol2.git
synced 2024-03-22 13:10:44 +08:00
force variable now works in traverse_set and proxy setters.
This commit is contained in:
parent
9c050230f3
commit
95ffd10283
|
@ -160,8 +160,6 @@ namespace sol {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct as_container_t;
|
struct as_container_t;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct force_t;
|
|
||||||
template <typename T>
|
|
||||||
struct nested;
|
struct nested;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct light;
|
struct light;
|
||||||
|
|
|
@ -118,7 +118,8 @@ namespace sol {
|
||||||
constexpr bool global = detail::is_global<top_level, decltype(std::get<I * 2>(std::forward<Pairs>(pairs)))...>::value;
|
constexpr bool global = detail::is_global<top_level, decltype(std::get<I * 2>(std::forward<Pairs>(pairs)))...>::value;
|
||||||
auto pp = stack::push_pop<global>(*this);
|
auto pp = stack::push_pop<global>(*this);
|
||||||
int table_index = pp.index_of(*this);
|
int table_index = pp.index_of(*this);
|
||||||
void(detail::swallow{ (stack::set_field<top_level, raw>(base_t::lua_state(),
|
lua_State* L = base_t::lua_state();
|
||||||
|
void(detail::swallow{ (stack::set_field<top_level, raw>(L,
|
||||||
std::get<I * 2>(std::forward<Pairs>(pairs)),
|
std::get<I * 2>(std::forward<Pairs>(pairs)),
|
||||||
std::get<I * 2 + 1>(std::forward<Pairs>(pairs)),
|
std::get<I * 2 + 1>(std::forward<Pairs>(pairs)),
|
||||||
table_index),
|
table_index),
|
||||||
|
@ -127,38 +128,58 @@ namespace sol {
|
||||||
|
|
||||||
template <bool global, bool raw, typename T, typename Key, typename... Keys>
|
template <bool global, bool raw, typename T, typename Key, typename... Keys>
|
||||||
decltype(auto) traverse_get_deep(int table_index, Key&& key, Keys&&... keys) const {
|
decltype(auto) traverse_get_deep(int table_index, Key&& key, Keys&&... keys) const {
|
||||||
stack::get_field<global, raw>(base_t::lua_state(), std::forward<Key>(key), table_index);
|
lua_State* L = base_t::lua_state();
|
||||||
(void)detail::swallow{ 0, (stack::get_field<false, raw>(base_t::lua_state(), std::forward<Keys>(keys), lua_gettop(base_t::lua_state())), 0)... };
|
stack::get_field<global, raw>(L, std::forward<Key>(key), table_index);
|
||||||
return stack::get<T>(base_t::lua_state());
|
(void)detail::swallow{ 0, (stack::get_field<false, raw>(L, std::forward<Keys>(keys), lua_gettop(L)), 0)... };
|
||||||
|
return stack::get<T>(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool global, bool raw, typename T, typename Key, typename... Keys>
|
template <bool global, bool raw, typename T, typename Key, typename... Keys>
|
||||||
decltype(auto) traverse_get_deep_optional(int& popcount, int table_index, Key&& key, Keys&&... keys) const {
|
decltype(auto) traverse_get_deep_optional(int& popcount, int table_index, Key&& key, Keys&&... keys) const {
|
||||||
|
lua_State* L = base_t::lua_state();
|
||||||
if constexpr (sizeof...(Keys) > 0) {
|
if constexpr (sizeof...(Keys) > 0) {
|
||||||
auto p = stack::probe_get_field<global>(base_t::lua_state(), std::forward<Key>(key), table_index);
|
auto p = stack::probe_get_field<global>(L, std::forward<Key>(key), table_index);
|
||||||
popcount += p.levels;
|
popcount += p.levels;
|
||||||
if (!p.success)
|
if (!p.success)
|
||||||
return T(nullopt);
|
return T(nullopt);
|
||||||
return traverse_get_deep_optional<false, raw, T>(popcount, lua_gettop(base_t::lua_state()), std::forward<Keys>(keys)...);
|
return traverse_get_deep_optional<false, raw, T>(popcount, lua_gettop(L), std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
using R = decltype(stack::get<T>(base_t::lua_state()));
|
using R = decltype(stack::get<T>(L));
|
||||||
auto p = stack::probe_get_field<global, raw, T>(base_t::lua_state(), std::forward<Key>(key), table_index);
|
auto p = stack::probe_get_field<global, raw, T>(L, std::forward<Key>(key), table_index);
|
||||||
popcount += p.levels;
|
popcount += p.levels;
|
||||||
if (!p.success)
|
if (!p.success)
|
||||||
return R(nullopt);
|
return R(nullopt);
|
||||||
return stack::get<T>(base_t::lua_state());
|
return stack::get<T>(L);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool global, bool raw, typename Key, typename... Keys>
|
template <bool global, bool raw, bool forced, typename Key, typename... Keys>
|
||||||
void traverse_set_deep(int table_index, Key&& key, Keys&&... keys) const {
|
void traverse_set_deep(int table_index, Key&& key, Keys&&... keys) const {
|
||||||
if constexpr (sizeof...(Keys) == 1) {
|
using KeyU = meta::unqualified_t<Key>;
|
||||||
stack::set_field<global, raw>(base_t::lua_state(), std::forward<Key>(key), std::forward<Keys>(keys)..., table_index);
|
lua_State* L = base_t::lua_state();
|
||||||
|
if constexpr(std::is_same_v<KeyU, force_t>) {
|
||||||
|
(void)key;
|
||||||
|
traverse_set_deep<false, raw, true>(table_index, std::forward<Keys>(keys)...);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
stack::get_field<global, raw>(base_t::lua_state(), std::forward<Key>(key), table_index);
|
if constexpr (sizeof...(Keys) == 1) {
|
||||||
traverse_set_deep<false, raw>(lua_gettop(base_t::lua_state()), std::forward<Keys>(keys)...);
|
stack::set_field<global, raw>(L, std::forward<Key>(key), std::forward<Keys>(keys)..., table_index);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if constexpr (forced) {
|
||||||
|
stack::probe p = stack::probe_get_field<global, raw>(L, key, table_index);
|
||||||
|
if (!p.success) {
|
||||||
|
constexpr bool is_seq = std::is_integral_v<KeyU>;
|
||||||
|
stack::set_field<global, raw>(L, key, new_table(static_cast<int>(is_seq), !static_cast<int>(is_seq)), table_index);
|
||||||
|
stack::get_field<global, raw>(L, std::forward<Key>(key), table_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stack::get_field<global, raw>(L, std::forward<Key>(key), table_index);
|
||||||
|
}
|
||||||
|
traverse_set_deep<false, raw, forced>(lua_gettop(L), std::forward<Keys>(keys)...);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,7 +251,7 @@ namespace sol {
|
||||||
if (!is_table<meta::unqualified_t<T>>::value) {
|
if (!is_table<meta::unqualified_t<T>>::value) {
|
||||||
auto pp = stack::push_pop(*this);
|
auto pp = stack::push_pop(*this);
|
||||||
constructor_handler handler{};
|
constructor_handler handler{};
|
||||||
stack::check<basic_table_core>(base_t::lua_state(), -1, handler);
|
stack::check<basic_table_core>(L, -1, handler);
|
||||||
}
|
}
|
||||||
#endif // Safety
|
#endif // Safety
|
||||||
}
|
}
|
||||||
|
@ -294,8 +315,9 @@ namespace sol {
|
||||||
constexpr static bool global = detail::is_global_v<top_level, Keys...>;
|
constexpr static bool global = detail::is_global_v<top_level, Keys...>;
|
||||||
auto pp = stack::push_pop<global>(*this);
|
auto pp = stack::push_pop<global>(*this);
|
||||||
int table_index = pp.index_of(*this);
|
int table_index = pp.index_of(*this);
|
||||||
auto pn = stack::pop_n(base_t::lua_state(), static_cast<int>(sizeof...(Keys) - 2));
|
lua_State* L = base_t::lua_state();
|
||||||
traverse_set_deep<top_level, false>(table_index, std::forward<Keys>(keys)...);
|
auto pn = stack::pop_n(L, static_cast<int>(sizeof...(Keys) - 2));
|
||||||
|
traverse_set_deep<top_level, false, false>(table_index, std::forward<Keys>(keys)...);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,8 +372,9 @@ namespace sol {
|
||||||
basic_table_core& traverse_raw_set(Keys&&... keys) {
|
basic_table_core& traverse_raw_set(Keys&&... keys) {
|
||||||
constexpr static bool global = detail::is_global_v<top_level, Keys...>;
|
constexpr static bool global = detail::is_global_v<top_level, Keys...>;
|
||||||
auto pp = stack::push_pop<global>(*this);
|
auto pp = stack::push_pop<global>(*this);
|
||||||
auto pn = stack::pop_n(base_t::lua_state(), static_cast<int>(sizeof...(Keys) - 2));
|
lua_State* L = base_t::lua_state();
|
||||||
traverse_set_deep<top_level, true>(std::forward<Keys>(keys)...);
|
auto pn = stack::pop_n(L, static_cast<int>(sizeof...(Keys) - 2));
|
||||||
|
traverse_set_deep<top_level, true, false>(std::forward<Keys>(keys)...);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,23 +427,24 @@ namespace sol {
|
||||||
|
|
||||||
template <typename Key = object, typename Value = object, typename Fx>
|
template <typename Key = object, typename Value = object, typename Fx>
|
||||||
void for_each(Fx&& fx) const {
|
void for_each(Fx&& fx) const {
|
||||||
|
lua_State* L = base_t::lua_state();
|
||||||
if constexpr (std::is_invocable_v<Fx, Key, Value>) {
|
if constexpr (std::is_invocable_v<Fx, Key, Value>) {
|
||||||
auto pp = stack::push_pop(*this);
|
auto pp = stack::push_pop(*this);
|
||||||
stack::push(base_t::lua_state(), lua_nil);
|
stack::push(L, lua_nil);
|
||||||
while (lua_next(base_t::lua_state(), -2)) {
|
while (lua_next(L, -2)) {
|
||||||
Key key(base_t::lua_state(), -2);
|
Key key(L, -2);
|
||||||
Value value(base_t::lua_state(), -1);
|
Value value(L, -1);
|
||||||
auto pn = stack::pop_n(base_t::lua_state(), 1);
|
auto pn = stack::pop_n(L, 1);
|
||||||
fx(key, value);
|
fx(key, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto pp = stack::push_pop(*this);
|
auto pp = stack::push_pop(*this);
|
||||||
stack::push(base_t::lua_state(), lua_nil);
|
stack::push(L, lua_nil);
|
||||||
while (lua_next(base_t::lua_state(), -2)) {
|
while (lua_next(L, -2)) {
|
||||||
Key key(base_t::lua_state(), -2);
|
Key key(L, -2);
|
||||||
Value value(base_t::lua_state(), -1);
|
Value value(L, -1);
|
||||||
auto pn = stack::pop_n(base_t::lua_state(), 1);
|
auto pn = stack::pop_n(L, 1);
|
||||||
std::pair<Key&, Value&> keyvalue(key, value);
|
std::pair<Key&, Value&> keyvalue(key, value);
|
||||||
fx(keyvalue);
|
fx(keyvalue);
|
||||||
}
|
}
|
||||||
|
@ -429,8 +453,9 @@ namespace sol {
|
||||||
|
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
auto pp = stack::push_pop(*this);
|
auto pp = stack::push_pop(*this);
|
||||||
lua_len(base_t::lua_state(), -1);
|
lua_State* L = base_t::lua_state();
|
||||||
return stack::pop<size_t>(base_t::lua_state());
|
lua_len(L, -1);
|
||||||
|
return stack::pop<size_t>(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty() const {
|
bool empty() const {
|
||||||
|
@ -468,7 +493,8 @@ namespace sol {
|
||||||
basic_table_core& add(Args&&... args) {
|
basic_table_core& add(Args&&... args) {
|
||||||
auto pp = stack::push_pop(*this);
|
auto pp = stack::push_pop(*this);
|
||||||
int table_index = pp.index_of(*this);
|
int table_index = pp.index_of(*this);
|
||||||
(void)detail::swallow{ 0, (stack::set_ref(base_t::lua_state(), std::forward<Args>(args), table_index), 0)... };
|
lua_State* L = base_t::lua_state();
|
||||||
|
(void)detail::swallow{ 0, (stack::set_ref(L, std::forward<Args>(args), table_index), 0)... };
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -496,18 +496,8 @@ namespace sol {
|
||||||
return as_container_t<T>(std::forward<T>(value));
|
return as_container_t<T>(std::forward<T>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
struct force_t {};
|
||||||
struct force_t : detail::ebco<T> {
|
constexpr inline force_t force = force_t();
|
||||||
private:
|
|
||||||
using base_t = detail::ebco<T>;
|
|
||||||
public:
|
|
||||||
using base_t::base_t;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
auto force(T&& value) {
|
|
||||||
return force_t<T>(std::forward<T>(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
struct this_state {
|
struct this_state {
|
||||||
lua_State* L;
|
lua_State* L;
|
||||||
|
|
|
@ -97,15 +97,3 @@ TEST_CASE("proxy/equality", "check to make sure equality tests work") {
|
||||||
REQUIRE_FALSE((lua["a"] != 2));
|
REQUIRE_FALSE((lua["a"] != 2));
|
||||||
#endif // clang screws up by trying to access int128 types that it doesn't support, even when we don't ask for them
|
#endif // clang screws up by trying to access int128 types that it doesn't support, even when we don't ask for them
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("proxy/force", "allow proxies to force creation of tables") {
|
|
||||||
sol::state lua;
|
|
||||||
lua.open_libraries(sol::lib::base, sol::lib::io);
|
|
||||||
|
|
||||||
sol::optional<int> not_there = lua["a"]["b"]["c"];
|
|
||||||
REQUIRE_FALSE(static_cast<bool>(not_there));
|
|
||||||
lua["a"].force()["b"].force()["c"] = 357;
|
|
||||||
sol::optional<int> totally_there = lua["a"]["b"]["c"];
|
|
||||||
REQUIRE(static_cast<bool>(totally_there));
|
|
||||||
REQUIRE(*totally_there == 357);
|
|
||||||
}
|
|
||||||
|
|
63
tests/runtime_tests/source/tables.force.cpp
Normal file
63
tests/runtime_tests/source/tables.force.cpp
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
// 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 <iostream>
|
||||||
|
|
||||||
|
TEST_CASE("tables/force", "allow force by way of key") {
|
||||||
|
sol::state lua;
|
||||||
|
lua.open_libraries(sol::lib::base, sol::lib::io);
|
||||||
|
|
||||||
|
sol::optional<int> not_there = lua["a"]["b"]["c"];
|
||||||
|
REQUIRE_FALSE(static_cast<bool>(not_there));
|
||||||
|
lua["a"].force()["b"].force()["c"] = 357;
|
||||||
|
sol::optional<int> totally_there = lua["a"]["b"]["c"];
|
||||||
|
REQUIRE(static_cast<bool>(totally_there));
|
||||||
|
REQUIRE(*totally_there == 357);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("tables/proxy force", "allow proxies to force creation of tables with explicit function") {
|
||||||
|
SECTION("explicit") {
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
sol::optional<int> not_there = lua["a"]["b"]["c"];
|
||||||
|
REQUIRE_FALSE(static_cast<bool>(not_there));
|
||||||
|
lua["a"].force()["b"].force()["c"] = 357;
|
||||||
|
sol::optional<int> totally_there = lua["a"]["b"]["c"];
|
||||||
|
REQUIRE(static_cast<bool>(totally_there));
|
||||||
|
REQUIRE(*totally_there == 357);
|
||||||
|
}
|
||||||
|
SECTION("key type") {
|
||||||
|
sol::state lua;
|
||||||
|
|
||||||
|
sol::optional<int> not_there = lua["a"]["b"]["c"];
|
||||||
|
REQUIRE_FALSE(static_cast<bool>(not_there));
|
||||||
|
lua[sol::force]["a"]["b"]["c"] = 357;
|
||||||
|
sol::optional<int> totally_there = lua["a"]["b"]["c"];
|
||||||
|
REQUIRE(static_cast<bool>(totally_there));
|
||||||
|
REQUIRE(*totally_there == 357);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user