aboutsummaryrefslogtreecommitdiff
path: root/src/deep.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/deep.cpp')
-rw-r--r--src/deep.cpp56
1 files changed, 1 insertions, 55 deletions
diff --git a/src/deep.cpp b/src/deep.cpp
index 6570e55..e0c2a39 100644
--- a/src/deep.cpp
+++ b/src/deep.cpp
@@ -34,10 +34,7 @@ THE SOFTWARE.
34 34
35#include "deep.h" 35#include "deep.h"
36 36
37#include "compat.h"
38#include "tools.h" 37#include "tools.h"
39#include "uniquekey.h"
40#include "universe.h"
41 38
42#include <bit> 39#include <bit>
43#include <cassert> 40#include <cassert>
@@ -105,7 +102,7 @@ static void LookupDeep(lua_State* L_)
105// ################################################################################################# 102// #################################################################################################
106 103
107// Return the registered factory for 'index' (deep userdata proxy), or nullptr if 'index' is not a deep userdata proxy. 104// Return the registered factory for 'index' (deep userdata proxy), or nullptr if 'index' is not a deep userdata proxy.
108[[nodiscard]] static inline DeepFactory* LookupFactory(lua_State* L_, int index_, LookupMode mode_) 105[[nodiscard]] DeepFactory* LookupFactory(lua_State* L_, int index_, LookupMode mode_)
109{ 106{
110 // when looking inside a keeper, we are 100% sure the object is a deep userdata 107 // when looking inside a keeper, we are 100% sure the object is a deep userdata
111 if (mode_ == LookupMode::FromKeeper) { 108 if (mode_ == LookupMode::FromKeeper) {
@@ -386,54 +383,3 @@ DeepPrelude* DeepFactory::toDeep(lua_State* L_, int index_) const
386 DeepPrelude** const proxy{ lua_tofulluserdata<DeepPrelude*>(L_, index_) }; 383 DeepPrelude** const proxy{ lua_tofulluserdata<DeepPrelude*>(L_, index_) };
387 return *proxy; 384 return *proxy;
388} 385}
389
390// #################################################################################################
391
392// Copy deep userdata between two separate Lua states (from L1 to L2)
393// Returns false if not a deep userdata, else true (unless an error occured)
394[[nodiscard]] bool InterCopyContext::tryCopyDeep() const
395{
396 DeepFactory* const factory{ LookupFactory(L1, L1_i, mode) };
397 if (factory == nullptr) {
398 return false; // not a deep userdata
399 }
400
401 STACK_CHECK_START_REL(L1, 0);
402 STACK_CHECK_START_REL(L2, 0);
403
404 // extract all uservalues of the source. unfortunately, the only way to know their count is to iterate until we fail
405 int nuv = 0;
406 while (lua_getiuservalue(L1, L1_i, nuv + 1) != LUA_TNONE) { // L1: ... u [uv]* nil
407 ++nuv;
408 }
409 // last call returned TNONE and pushed nil, that we don't need
410 lua_pop(L1, 1); // L1: ... u [uv]*
411 STACK_CHECK(L1, nuv);
412
413 DeepPrelude* const u{ *lua_tofulluserdata<DeepPrelude*>(L1, L1_i) };
414 char const* errmsg{ DeepFactory::PushDeepProxy(L2, u, nuv, mode) }; // L1: ... u [uv]* L2: u
415 if (errmsg != nullptr) {
416 raise_luaL_error(getErrL(), errmsg);
417 }
418
419 // transfer all uservalues of the source in the destination
420 {
421 InterCopyContext c{ U, L2, L1, L2_cache_i, {}, VT::NORMAL, mode, name };
422 int const clone_i{ lua_gettop(L2) };
423 while (nuv) {
424 c.L1_i = SourceIndex{ lua_absindex(L1, -1) };
425 if (!c.inter_copy_one()) { // L1: ... u [uv]* L2: u uv
426 raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1));
427 }
428 lua_pop(L1, 1); // L1: ... u [uv]*
429 // this pops the value from the stack
430 lua_setiuservalue(L2, clone_i, nuv); // L2: u
431 --nuv;
432 }
433 }
434
435 STACK_CHECK(L2, 1);
436 STACK_CHECK(L1, 0);
437
438 return true;
439} \ No newline at end of file