diff options
Diffstat (limited to 'src/tools.cpp')
-rw-r--r-- | src/tools.cpp | 31 |
1 files changed, 14 insertions, 17 deletions
diff --git a/src/tools.cpp b/src/tools.cpp index 8ddce75..ba0785b 100644 --- a/src/tools.cpp +++ b/src/tools.cpp | |||
@@ -90,26 +90,26 @@ static constexpr int kWriterReturnCode{ 666 }; | |||
90 | // ################################################################################################# | 90 | // ################################################################################################# |
91 | 91 | ||
92 | // inspired from tconcat() in ltablib.c | 92 | // inspired from tconcat() in ltablib.c |
93 | [[nodiscard]] static char const* luaG_pushFQN(lua_State* L_, int t_, int last_, size_t* length_) | 93 | [[nodiscard]] static std::string_view luaG_pushFQN(lua_State* L_, int t_, int last_) |
94 | { | 94 | { |
95 | luaL_Buffer _b; | 95 | luaL_Buffer _b; |
96 | STACK_CHECK_START_REL(L_, 0); | 96 | STACK_CHECK_START_REL(L_, 0); |
97 | // Lua 5.4 pushes &b as light userdata on the stack. be aware of it... | 97 | // Lua 5.4 pushes &b as light userdata on the stack. be aware of it... |
98 | luaL_buffinit(L_, &_b); // L_: ... {} ... &b? | 98 | luaL_buffinit(L_, &_b); // L_: ... {} ... &b? |
99 | int i = 1; | 99 | int _i{ 1 }; |
100 | for (; i < last_; ++i) { | 100 | for (; _i < last_; ++_i) { |
101 | lua_rawgeti(L_, t_, i); | 101 | lua_rawgeti(L_, t_, _i); |
102 | luaL_addvalue(&_b); | 102 | luaL_addvalue(&_b); |
103 | luaL_addlstring(&_b, "/", 1); | 103 | luaL_addlstring(&_b, "/", 1); |
104 | } | 104 | } |
105 | if (i == last_) { // add last value (if interval was not empty) | 105 | if (_i == last_) { // add last value (if interval was not empty) |
106 | lua_rawgeti(L_, t_, i); | 106 | lua_rawgeti(L_, t_, _i); |
107 | luaL_addvalue(&_b); | 107 | luaL_addvalue(&_b); |
108 | } | 108 | } |
109 | // &b is popped at that point (-> replaced by the result) | 109 | // &b is popped at that point (-> replaced by the result) |
110 | luaL_pushresult(&_b); // L_: ... {} ... "<result>" | 110 | luaL_pushresult(&_b); // L_: ... {} ... "<result>" |
111 | STACK_CHECK(L_, 1); | 111 | STACK_CHECK(L_, 1); |
112 | return lua_tolstring(L_, -1, length_); | 112 | return lua_tostringview(L_, -1); |
113 | } | 113 | } |
114 | 114 | ||
115 | // ################################################################################################# | 115 | // ################################################################################################# |
@@ -129,7 +129,6 @@ static void update_lookup_entry(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L | |||
129 | // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i | 129 | // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i |
130 | int const _fqn{ ctxBase_ + 1 }; | 130 | int const _fqn{ ctxBase_ + 1 }; |
131 | 131 | ||
132 | DEBUGSPEW_CODE(char const* _newName); | ||
133 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "update_lookup_entry()\n" INDENT_END(U_))); | 132 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "update_lookup_entry()\n" INDENT_END(U_))); |
134 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U_ }); | 133 | DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U_ }); |
135 | 134 | ||
@@ -137,16 +136,14 @@ static void update_lookup_entry(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L | |||
137 | // first, raise an error if the function is already known | 136 | // first, raise an error if the function is already known |
138 | lua_pushvalue(L_, -1); // L_: ... {bfc} k o o | 137 | lua_pushvalue(L_, -1); // L_: ... {bfc} k o o |
139 | lua_rawget(L_, _dest); // L_: ... {bfc} k o name? | 138 | lua_rawget(L_, _dest); // L_: ... {bfc} k o name? |
140 | size_t _prevNameLength; | 139 | std::string_view const _prevName{ lua_tostringview(L_, -1) }; // nullptr if we got nil (first encounter of this object) |
141 | char const* const _prevName{ lua_tolstring(L_, -1, &_prevNameLength) }; // nullptr if we got nil (first encounter of this object) | ||
142 | // push name in fqn stack (note that concatenation will crash if name is a not string or a number) | 140 | // push name in fqn stack (note that concatenation will crash if name is a not string or a number) |
143 | lua_pushvalue(L_, -3); // L_: ... {bfc} k o name? k | 141 | lua_pushvalue(L_, -3); // L_: ... {bfc} k o name? k |
144 | LUA_ASSERT(L_, lua_type(L_, -1) == LUA_TNUMBER || lua_type(L_, -1) == LUA_TSTRING); | 142 | LUA_ASSERT(L_, lua_type(L_, -1) == LUA_TNUMBER || lua_type(L_, -1) == LUA_TSTRING); |
145 | ++depth_; | 143 | ++depth_; |
146 | lua_rawseti(L_, _fqn, depth_); // L_: ... {bfc} k o name? | 144 | lua_rawseti(L_, _fqn, depth_); // L_: ... {bfc} k o name? |
147 | // generate name | 145 | // generate name |
148 | size_t _newNameLength; | 146 | std::string_view const _newName{ luaG_pushFQN(L_, _fqn, depth_) }; // L_: ... {bfc} k o name? "f.q.n" |
149 | DEBUGSPEW_OR_NOT(_newName, std::ignore) = luaG_pushFQN(L_, _fqn, depth_, &_newNameLength); // L_: ... {bfc} k o name? "f.q.n" | ||
150 | // Lua 5.2 introduced a hash randomizer seed which causes table iteration to yield a different key order | 147 | // Lua 5.2 introduced a hash randomizer seed which causes table iteration to yield a different key order |
151 | // on different VMs even when the tables are populated the exact same way. | 148 | // on different VMs even when the tables are populated the exact same way. |
152 | // When Lua is built with compatibility options (such as LUA_COMPAT_ALL), | 149 | // When Lua is built with compatibility options (such as LUA_COMPAT_ALL), |
@@ -156,13 +153,13 @@ static void update_lookup_entry(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L | |||
156 | // Also, nothing prevents any external module from exposing a given object under several names, so... | 153 | // Also, nothing prevents any external module from exposing a given object under several names, so... |
157 | // Therefore, when we encounter an object for which a name was previously registered, we need to select the names | 154 | // Therefore, when we encounter an object for which a name was previously registered, we need to select the names |
158 | // based on some sorting order so that we end up with the same name in all databases whatever order the table walk yielded | 155 | // based on some sorting order so that we end up with the same name in all databases whatever order the table walk yielded |
159 | if (_prevName != nullptr && (_prevNameLength < _newNameLength || lua_lessthan(L_, -2, -1))) { | 156 | if (!_prevName.empty() && (_prevName.size() < _newName.size() || lua_lessthan(L_, -2, -1))) { |
160 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%s '%s' remained named '%s'\n" INDENT_END(U_), lua_typename(L_, lua_type(L_, -3)), _newName, _prevName)); | 157 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%s '%s' remained named '%s'\n" INDENT_END(U_), lua_typename(L_, lua_type(L_, -3)), _newName.data(), _prevName.data())); |
161 | // the previous name is 'smaller' than the one we just generated: keep it! | 158 | // the previous name is 'smaller' than the one we just generated: keep it! |
162 | lua_pop(L_, 3); // L_: ... {bfc} k | 159 | lua_pop(L_, 3); // L_: ... {bfc} k |
163 | } else { | 160 | } else { |
164 | // the name we generated is either the first one, or a better fit for our purposes | 161 | // the name we generated is either the first one, or a better fit for our purposes |
165 | if (_prevName) { | 162 | if (!_prevName.empty()) { |
166 | // clear the previous name for the database to avoid clutter | 163 | // clear the previous name for the database to avoid clutter |
167 | lua_insert(L_, -2); // L_: ... {bfc} k o "f.q.n" prevName | 164 | lua_insert(L_, -2); // L_: ... {bfc} k o "f.q.n" prevName |
168 | // t[prevName] = nil | 165 | // t[prevName] = nil |
@@ -171,7 +168,7 @@ static void update_lookup_entry(DEBUGSPEW_PARAM_COMMA(Universe* U_) lua_State* L | |||
171 | } else { | 168 | } else { |
172 | lua_remove(L_, -2); // L_: ... {bfc} k o "f.q.n" | 169 | lua_remove(L_, -2); // L_: ... {bfc} k o "f.q.n" |
173 | } | 170 | } |
174 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%s '%s'\n" INDENT_END(U_), lua_typename(L_, lua_type(L_, -2)), _newName)); | 171 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "%s '%s'\n" INDENT_END(U_), lua_typename(L_, lua_type(L_, -2)), _newName.data())); |
175 | // prepare the stack for database feed | 172 | // prepare the stack for database feed |
176 | lua_pushvalue(L_, -1); // L_: ... {bfc} k o "f.q.n" "f.q.n" | 173 | lua_pushvalue(L_, -1); // L_: ... {bfc} k o "f.q.n" "f.q.n" |
177 | lua_pushvalue(L_, -3); // L_: ... {bfc} k o "f.q.n" "f.q.n" o | 174 | lua_pushvalue(L_, -3); // L_: ... {bfc} k o "f.q.n" "f.q.n" o |
@@ -390,7 +387,7 @@ void populate_func_lookup_table(lua_State* L_, int i_, char const* name_) | |||
390 | // update shortest name | 387 | // update shortest name |
391 | if (depth_ < shortest_) { | 388 | if (depth_ < shortest_) { |
392 | shortest_ = depth_; | 389 | shortest_ = depth_; |
393 | std::ignore = luaG_pushFQN(L_, kFQN, depth_, nullptr); // L_: o "r" {c} {fqn} ... {?} k v "fqn" | 390 | std::ignore = luaG_pushFQN(L_, kFQN, depth_); // L_: o "r" {c} {fqn} ... {?} k v "fqn" |
394 | lua_replace(L_, kResult); // L_: o "r" {c} {fqn} ... {?} k v | 391 | lua_replace(L_, kResult); // L_: o "r" {c} {fqn} ... {?} k v |
395 | } | 392 | } |
396 | // no need to search further at this level | 393 | // no need to search further at this level |