diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-10 16:21:31 +0200 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-06-10 16:21:31 +0200 |
commit | 3f5c16116a3a7740ac4ac62b663661d772543c2e (patch) | |
tree | 884df73600bd680929f7ad0ebdfadd087b4841e4 /src | |
parent | 3763be94cdd1a5cf26fec0f09784b18188fd3054 (diff) | |
download | lanes-3f5c16116a3a7740ac4ac62b663661d772543c2e.tar.gz lanes-3f5c16116a3a7740ac4ac62b663661d772543c2e.tar.bz2 lanes-3f5c16116a3a7740ac4ac62b663661d772543c2e.zip |
Replaced __lanesignore with __lanesconvert
Diffstat (limited to 'src')
-rw-r--r-- | src/intercopycontext.cpp | 87 | ||||
-rw-r--r-- | src/intercopycontext.h | 3 |
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 | ||
535 | LuaType 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; |