aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-06-10 16:21:31 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2024-06-10 16:21:31 +0200
commit3f5c16116a3a7740ac4ac62b663661d772543c2e (patch)
tree884df73600bd680929f7ad0ebdfadd087b4841e4 /src
parent3763be94cdd1a5cf26fec0f09784b18188fd3054 (diff)
downloadlanes-3f5c16116a3a7740ac4ac62b663661d772543c2e.tar.gz
lanes-3f5c16116a3a7740ac4ac62b663661d772543c2e.tar.bz2
lanes-3f5c16116a3a7740ac4ac62b663661d772543c2e.zip
Replaced __lanesignore with __lanesconvert
Diffstat (limited to 'src')
-rw-r--r--src/intercopycontext.cpp87
-rw-r--r--src/intercopycontext.h3
2 files changed, 75 insertions, 15 deletions
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp
index c7fcf14..a5fd400 100644
--- a/src/intercopycontext.cpp
+++ b/src/intercopycontext.cpp
@@ -532,6 +532,76 @@ void InterCopyContext::inter_copy_keyvaluepair() const
532 532
533// ################################################################################################# 533// #################################################################################################
534 534
535LuaType InterCopyContext::processConversion() const
536{
537 static constexpr int kPODmask = (1 << LUA_TNIL) | (1 << LUA_TBOOLEAN) | (1 << LUA_TLIGHTUSERDATA) | (1 << LUA_TNUMBER) | (1 << LUA_TSTRING);
538
539 LuaType _val_type{ luaG_type(L1, L1_i) };
540
541 STACK_CHECK_START_REL(L1, 0);
542
543 // it's a POD: nothing to do
544 if (((1 << static_cast<int>(_val_type)) & kPODmask) != 0) {
545 return _val_type;
546 }
547
548 // no metatable: nothing to do
549 if (!lua_getmetatable(L1, L1_i)) { // L1: ...
550 STACK_CHECK(L1, 0);
551 return _val_type;
552 }
553 // we have a metatable // L1: ... mt
554 static constexpr std::string_view kConvertField{ "__lanesconvert" };
555 LuaType const _converterType{ luaG_getfield(L1, -1, kConvertField) }; // L1: ... mt kConvertField
556 switch (_converterType) {
557 case LuaType::NIL:
558 // no __lanesconvert, nothing to do
559 lua_pop(L1, 2); // L1: ...
560 break;
561
562 case LuaType::LIGHTUSERDATA:
563 if (kNilSentinel.equals(L1, -1)) {
564 DEBUGSPEW_CODE(DebugSpew(U) << "converted " << luaG_typename(L1, _val_type) << " to nil" << std::endl);
565 lua_replace(L1, L1_i); // L1: ... mt
566 lua_pop(L1, 1); // L1: ...
567 _val_type = _converterType;
568 } else {
569 raise_luaL_error(getErrL(), "Invalid %s type %s", kConvertField.data(), luaG_typename(L1, _converterType).data());
570 }
571 break;
572
573 case LuaType::STRING:
574 // kConvertField == "decay" -> replace source value with it's pointer
575 if (std::string_view const _mode{ luaG_tostring(L1, -1) }; _mode == "decay") {
576 lua_pop(L1, 1); // L1: ... mt
577 lua_pushlightuserdata(L1, const_cast<void*>(lua_topointer(L1, L1_i))); // L1: ... mt decayed
578 lua_replace(L1, L1_i); // L1: ... mt
579 lua_pop(L1, 1); // L1: ...
580 _val_type = LuaType::LIGHTUSERDATA;
581 } else {
582 raise_luaL_error(getErrL(), "Invalid %s mode '%s'", kConvertField.data(), _mode.data());
583 }
584 break;
585
586 case LuaType::FUNCTION:
587 lua_pushvalue(L1, L1_i); // L1: ... mt kConvertField val
588 std::ignore = luaG_pushstring(L1, mode == LookupMode::ToKeeper ? "keeper" : "regular"); // L1: ... mt kConvertField val string
589 lua_call(L1, 2, 1); // val:kConvertField(str) -> result // L1: ... mt kConvertField converted
590 lua_replace(L1, L1_i); // L1: ... mt
591 lua_pop(L1, 1); // L1: ... mt
592 _val_type = luaG_type(L1, L1_i);
593 break;
594
595 default:
596 raise_luaL_error(getErrL(), "Invalid %s type %s", kConvertField.data(), luaG_typename(L1, _converterType).data());
597 }
598 STACK_CHECK(L1, 0);
599 LUA_ASSERT(getErrL(), luaG_type(L1, L1_i) == _val_type);
600 return _val_type;
601}
602
603// #################################################################################################
604
535[[nodiscard]] bool InterCopyContext::push_cached_metatable() const 605[[nodiscard]] bool InterCopyContext::push_cached_metatable() const
536{ 606{
537 STACK_CHECK_START_REL(L1, 0); 607 STACK_CHECK_START_REL(L1, 0);
@@ -1085,21 +1155,10 @@ namespace {
1085 DEBUGSPEW_CODE(DebugSpew(U) << "inter_copy_one()" << std::endl); 1155 DEBUGSPEW_CODE(DebugSpew(U) << "inter_copy_one()" << std::endl);
1086 DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U }); 1156 DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U });
1087 1157
1088 LuaType _val_type{ luaG_type(L1, L1_i) }; 1158 // replace the value at L1_i with the result of a conversion if required
1089 DEBUGSPEW_CODE(DebugSpew(U) << local::sLuaTypeNames[static_cast<int>(_val_type)] << " " << local::sValueTypeNames[static_cast<int>(vt)] << ": "); 1159 LuaType const _val_type{ processConversion() };
1090
1091 // Non-POD can be skipped if its metatable contains { __lanesignore = true }
1092 if (((1 << static_cast<int>(_val_type)) & kPODmask) == 0) {
1093 if (lua_getmetatable(L1, L1_i)) { // L1: ... mt
1094 LuaType const _type{ luaG_getfield(L1, -1, "__lanesignore") }; // L1: ... mt ignore?
1095 if (_type == LuaType::BOOLEAN && lua_toboolean(L1, -1)) {
1096 DEBUGSPEW_CODE(DebugSpew(U) << "__lanesignore -> LUA_TNIL" << std::endl);
1097 _val_type = LuaType::NIL;
1098 }
1099 lua_pop(L1, 2); // L1: ...
1100 }
1101 }
1102 STACK_CHECK(L1, 0); 1160 STACK_CHECK(L1, 0);
1161 DEBUGSPEW_CODE(DebugSpew(U) << local::sLuaTypeNames[static_cast<int>(_val_type)] << " " << local::sValueTypeNames[static_cast<int>(vt)] << ": ");
1103 1162
1104 // Lets push nil to L2 if the object should be ignored 1163 // Lets push nil to L2 if the object should be ignored
1105 bool _ret{ true }; 1164 bool _ret{ true };
diff --git a/src/intercopycontext.h b/src/intercopycontext.h
index ffa825f..459551e 100644
--- a/src/intercopycontext.h
+++ b/src/intercopycontext.h
@@ -38,10 +38,11 @@ class InterCopyContext
38 char const* name; // that one can change when we reuse the context 38 char const* name; // that one can change when we reuse the context
39 39
40 private: 40 private:
41 [[nodiscard]] std::string_view findLookupName() const;
41 // when mode == LookupMode::FromKeeper, L1 is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error 42 // when mode == LookupMode::FromKeeper, L1 is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error
42 // whon mode != LookupMode::FromKeeper, L1 is not a keeper state, therefore L1 is the state where we want to raise the error 43 // whon mode != LookupMode::FromKeeper, L1 is not a keeper state, therefore L1 is the state where we want to raise the error
43 lua_State* getErrL() const { return (mode == LookupMode::FromKeeper) ? L2 : L1; } 44 lua_State* getErrL() const { return (mode == LookupMode::FromKeeper) ? L2 : L1; }
44 [[nodiscard]] std::string_view findLookupName() const; 45 [[nodiscard]] LuaType processConversion() const;
45 46
46 // for use in copy_cached_func 47 // for use in copy_cached_func
47 void copy_func() const; 48 void copy_func() const;