diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cancel.cpp | 16 | ||||
-rw-r--r-- | src/cancel.h | 4 | ||||
-rw-r--r-- | src/compat.h | 11 | ||||
-rw-r--r-- | src/intercopycontext.cpp | 87 | ||||
-rw-r--r-- | src/lanes.cpp | 9 | ||||
-rw-r--r-- | src/lindafactory.cpp | 9 | ||||
-rw-r--r-- | src/tools.cpp | 31 | ||||
-rw-r--r-- | src/universe.cpp | 6 |
8 files changed, 88 insertions, 85 deletions
diff --git a/src/cancel.cpp b/src/cancel.cpp index ff7af1e..f093905 100644 --- a/src/cancel.cpp +++ b/src/cancel.cpp | |||
@@ -162,20 +162,20 @@ CancelResult thread_cancel(Lane* lane_, CancelOp op_, int hookCount_, std::chron | |||
162 | // ################################################################################################# | 162 | // ################################################################################################# |
163 | // ################################################################################################# | 163 | // ################################################################################################# |
164 | 164 | ||
165 | CancelOp which_cancel_op(char const* opString_) | 165 | CancelOp which_cancel_op(std::string_view const& opString_) |
166 | { | 166 | { |
167 | CancelOp _op{ CancelOp::Invalid }; | 167 | CancelOp _op{ CancelOp::Invalid }; |
168 | if (strcmp(opString_, "hard") == 0) { | 168 | if (opString_ == "hard") { |
169 | _op = CancelOp::Hard; | 169 | _op = CancelOp::Hard; |
170 | } else if (strcmp(opString_, "soft") == 0) { | 170 | } else if (opString_ == "soft") { |
171 | _op = CancelOp::Soft; | 171 | _op = CancelOp::Soft; |
172 | } else if (strcmp(opString_, "call") == 0) { | 172 | } else if (opString_== "call") { |
173 | _op = CancelOp::MaskCall; | 173 | _op = CancelOp::MaskCall; |
174 | } else if (strcmp(opString_, "ret") == 0) { | 174 | } else if (opString_ == "ret") { |
175 | _op = CancelOp::MaskRet; | 175 | _op = CancelOp::MaskRet; |
176 | } else if (strcmp(opString_, "line") == 0) { | 176 | } else if (opString_ == "line") { |
177 | _op = CancelOp::MaskLine; | 177 | _op = CancelOp::MaskLine; |
178 | } else if (strcmp(opString_, "count") == 0) { | 178 | } else if (opString_ == "count") { |
179 | _op = CancelOp::MaskCount; | 179 | _op = CancelOp::MaskCount; |
180 | } | 180 | } |
181 | return _op; | 181 | return _op; |
@@ -186,7 +186,7 @@ CancelOp which_cancel_op(char const* opString_) | |||
186 | [[nodiscard]] static CancelOp which_cancel_op(lua_State* L_, int idx_) | 186 | [[nodiscard]] static CancelOp which_cancel_op(lua_State* L_, int idx_) |
187 | { | 187 | { |
188 | if (lua_type(L_, idx_) == LUA_TSTRING) { | 188 | if (lua_type(L_, idx_) == LUA_TSTRING) { |
189 | char const* const _str{ lua_tostring(L_, idx_) }; | 189 | std::string_view const _str{ lua_tostringview(L_, idx_) }; |
190 | CancelOp _op{ which_cancel_op(_str) }; | 190 | CancelOp _op{ which_cancel_op(_str) }; |
191 | lua_remove(L_, idx_); // argument is processed, remove it | 191 | lua_remove(L_, idx_); // argument is processed, remove it |
192 | if (_op == CancelOp::Invalid) { | 192 | if (_op == CancelOp::Invalid) { |
diff --git a/src/cancel.h b/src/cancel.h index 1918df3..bac8b05 100644 --- a/src/cancel.h +++ b/src/cancel.h | |||
@@ -14,6 +14,8 @@ extern "C" | |||
14 | #include "macros_and_utils.h" | 14 | #include "macros_and_utils.h" |
15 | #include "uniquekey.h" | 15 | #include "uniquekey.h" |
16 | 16 | ||
17 | #include <string_view> | ||
18 | |||
17 | // ################################################################################################# | 19 | // ################################################################################################# |
18 | 20 | ||
19 | class Lane; // forward | 21 | class Lane; // forward |
@@ -48,7 +50,7 @@ enum class CancelOp | |||
48 | // xxh64 of string "kCancelError" generated at https://www.pelock.com/products/hash-calculator | 50 | // xxh64 of string "kCancelError" generated at https://www.pelock.com/products/hash-calculator |
49 | static constexpr UniqueKey kCancelError{ 0x0630345FEF912746ull, "lanes.cancel_error" }; // 'raise_cancel_error' sentinel | 51 | static constexpr UniqueKey kCancelError{ 0x0630345FEF912746ull, "lanes.cancel_error" }; // 'raise_cancel_error' sentinel |
50 | 52 | ||
51 | [[nodiscard]] CancelOp which_cancel_op(char const* opString_); | 53 | [[nodiscard]] CancelOp which_cancel_op(std::string_view const& opString_); |
52 | [[nodiscard]] CancelResult thread_cancel(Lane* lane_, CancelOp op_, int hookCount_, std::chrono::time_point<std::chrono::steady_clock> until_, bool wakeLane_); | 54 | [[nodiscard]] CancelResult thread_cancel(Lane* lane_, CancelOp op_, int hookCount_, std::chrono::time_point<std::chrono::steady_clock> until_, bool wakeLane_); |
53 | 55 | ||
54 | [[noreturn]] static inline void raise_cancel_error(lua_State* L_) | 56 | [[noreturn]] static inline void raise_cancel_error(lua_State* L_) |
diff --git a/src/compat.h b/src/compat.h index 0e95cde..3fb4e2d 100644 --- a/src/compat.h +++ b/src/compat.h | |||
@@ -25,6 +25,7 @@ extern "C" | |||
25 | #endif // LUA_JITLIBNAME | 25 | #endif // LUA_JITLIBNAME |
26 | 26 | ||
27 | #include <cassert> | 27 | #include <cassert> |
28 | #include <string_view> | ||
28 | 29 | ||
29 | // code is now preferring Lua 5.4 API | 30 | // code is now preferring Lua 5.4 API |
30 | 31 | ||
@@ -249,3 +250,13 @@ inline constexpr LuaError ToLuaError(int rc_) | |||
249 | // ################################################################################################# | 250 | // ################################################################################################# |
250 | 251 | ||
251 | LuaType luaG_getmodule(lua_State* L_, char const* name_); | 252 | LuaType luaG_getmodule(lua_State* L_, char const* name_); |
253 | |||
254 | // ################################################################################################# | ||
255 | |||
256 | // a replacement of lua_tolstring | ||
257 | inline std::string_view lua_tostringview(lua_State* L_, int idx_) | ||
258 | { | ||
259 | size_t _len{ 0 }; | ||
260 | char const* _str{ lua_tolstring(L_, idx_, &_len) }; | ||
261 | return std::string_view{ _str, _len }; | ||
262 | } | ||
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp index 2f83400..1487afd 100644 --- a/src/intercopycontext.cpp +++ b/src/intercopycontext.cpp | |||
@@ -96,38 +96,37 @@ THE SOFTWARE. | |||
96 | lua_pushvalue(L1, L1_i); // L1: ... v ... {} v | 96 | lua_pushvalue(L1, L1_i); // L1: ... v ... {} v |
97 | lua_rawget(L1, -2); // L1: ... v ... {} "f.q.n" | 97 | lua_rawget(L1, -2); // L1: ... v ... {} "f.q.n" |
98 | } | 98 | } |
99 | size_t _len{ 0 }; | 99 | std::string_view _fqn{ lua_tostringview(L1, -1) }; |
100 | char const* _fqn{ lua_tolstring(L1, -1, &_len) }; | ||
101 | DEBUGSPEW_CODE(Universe* const _U = universe_get(L1)); | 100 | DEBUGSPEW_CODE(Universe* const _U = universe_get(L1)); |
102 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END(_U), _fqn)); | 101 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END(_U), _fqn.data())); |
103 | // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database | 102 | // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database |
104 | lua_pop(L1, (mode == LookupMode::FromKeeper) ? 1 : 2); // L1: ... v ... | 103 | lua_pop(L1, (mode == LookupMode::FromKeeper) ? 1 : 2); // L1: ... v ... |
105 | STACK_CHECK(L1, 0); | 104 | STACK_CHECK(L1, 0); |
106 | if (nullptr == _fqn && !lua_istable(L1, L1_i)) { // raise an error if we try to send an unknown function (but not for tables) | 105 | if (_fqn.empty() && !lua_istable(L1, L1_i)) { // raise an error if we try to send an unknown function (but not for tables) |
107 | _len = 0; // just in case | 106 | _fqn = std::string_view{}; // just in case |
108 | // try to discover the name of the function we want to send | 107 | // try to discover the name of the function we want to send |
109 | lua_getglobal(L1, "decoda_name"); // L1: ... v ... decoda_name | 108 | lua_getglobal(L1, "decoda_name"); // L1: ... v ... decoda_name |
110 | char const* from{ lua_tostring(L1, -1) }; | 109 | char const* _from{ lua_tostring(L1, -1) }; |
111 | lua_pushcfunction(L1, luaG_nameof); // L1: ... v ... decoda_name luaG_nameof | 110 | lua_pushcfunction(L1, luaG_nameof); // L1: ... v ... decoda_name luaG_nameof |
112 | lua_pushvalue(L1, L1_i); // L1: ... v ... decoda_name luaG_nameof t | 111 | lua_pushvalue(L1, L1_i); // L1: ... v ... decoda_name luaG_nameof t |
113 | lua_call(L1, 1, 2); // L1: ... v ... decoda_name "type" "name"|nil | 112 | lua_call(L1, 1, 2); // L1: ... v ... decoda_name "type" "name"|nil |
114 | char const* typewhat{ (lua_type(L1, -2) == LUA_TSTRING) ? lua_tostring(L1, -2) : luaL_typename(L1, -2) }; | 113 | char const* _typewhat{ (lua_type(L1, -2) == LUA_TSTRING) ? lua_tostring(L1, -2) : luaL_typename(L1, -2) }; |
115 | // second return value can be nil if the table was not found | 114 | // second return value can be nil if the table was not found |
116 | // probable reason: the function was removed from the source Lua state before Lanes was required. | 115 | // probable reason: the function was removed from the source Lua state before Lanes was required. |
117 | char const *what, *gotchaA, *gotchaB; | 116 | char const *_what, *_gotchaA, *_gotchaB; |
118 | if (lua_isnil(L1, -1)) { | 117 | if (lua_isnil(L1, -1)) { |
119 | gotchaA = " referenced by"; | 118 | _gotchaA = " referenced by"; |
120 | gotchaB = "\n(did you remove it from the source Lua state before requiring Lanes?)"; | 119 | _gotchaB = "\n(did you remove it from the source Lua state before requiring Lanes?)"; |
121 | what = name; | 120 | _what = name; |
122 | } else { | 121 | } else { |
123 | gotchaA = ""; | 122 | _gotchaA = ""; |
124 | gotchaB = ""; | 123 | _gotchaB = ""; |
125 | what = (lua_type(L1, -1) == LUA_TSTRING) ? lua_tostring(L1, -1) : luaL_typename(L1, -1); | 124 | _what = (lua_type(L1, -1) == LUA_TSTRING) ? lua_tostring(L1, -1) : luaL_typename(L1, -1); |
126 | } | 125 | } |
127 | raise_luaL_error(L1, "%s%s '%s' not found in %s origin transfer database.%s", typewhat, gotchaA, what, from ? from : "main", gotchaB); | 126 | raise_luaL_error(L1, "%s%s '%s' not found in %s origin transfer database.%s", _typewhat, _gotchaA, _what, _from ? _from : "main", _gotchaB); |
128 | } | 127 | } |
129 | STACK_CHECK(L1, 0); | 128 | STACK_CHECK(L1, 0); |
130 | return std::string_view{ _fqn, _len }; | 129 | return _fqn; |
131 | } | 130 | } |
132 | 131 | ||
133 | // ################################################################################################# | 132 | // ################################################################################################# |
@@ -208,7 +207,7 @@ void InterCopyContext::copy_func() const | |||
208 | 207 | ||
209 | // transfer the bytecode, then the upvalues, to create a similar closure | 208 | // transfer the bytecode, then the upvalues, to create a similar closure |
210 | { | 209 | { |
211 | char const* fname = nullptr; | 210 | char const* _fname{}; |
212 | #define LOG_FUNC_INFO 0 | 211 | #define LOG_FUNC_INFO 0 |
213 | #if LOG_FUNC_INFO | 212 | #if LOG_FUNC_INFO |
214 | // "To get information about a function you push it onto the | 213 | // "To get information about a function you push it onto the |
@@ -219,14 +218,13 @@ void InterCopyContext::copy_func() const | |||
219 | lua_pushvalue(L1, L1_i); // L1: ... b f | 218 | lua_pushvalue(L1, L1_i); // L1: ... b f |
220 | // fills 'fname' 'namewhat' and 'linedefined', pops function | 219 | // fills 'fname' 'namewhat' and 'linedefined', pops function |
221 | lua_getinfo(L1, ">nS", &_ar); // L1: ... b | 220 | lua_getinfo(L1, ">nS", &_ar); // L1: ... b |
222 | fname = _ar.namewhat; | 221 | _fname = _ar.namewhat; |
223 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "FNAME: %s @ %d" INDENT_END(U), _ar.short_src, _ar.linedefined)); // just gives nullptr | 222 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "FNAME: %s @ %d" INDENT_END(U), _ar.short_src, _ar.linedefined)); // just gives nullptr |
224 | } | 223 | } |
225 | #endif // LOG_FUNC_INFO | 224 | #endif // LOG_FUNC_INFO |
226 | { | 225 | { |
227 | size_t _sz; | 226 | std::string_view const _bytecode{ lua_tostringview(L1, -1) }; // L1: ... b |
228 | char const* _s{ lua_tolstring(L1, -1, &_sz) }; // L1: ... b | 227 | LUA_ASSERT(L1, !_bytecode.empty()); |
229 | LUA_ASSERT(L1, _s && _sz); | ||
230 | STACK_GROW(L2, 2); | 228 | STACK_GROW(L2, 2); |
231 | // Note: Line numbers seem to be taken precisely from the | 229 | // Note: Line numbers seem to be taken precisely from the |
232 | // original function. 'fname' is not used since the chunk | 230 | // original function. 'fname' is not used since the chunk |
@@ -234,12 +232,12 @@ void InterCopyContext::copy_func() const | |||
234 | // | 232 | // |
235 | // TBD: Can we get the function's original name through, as well? | 233 | // TBD: Can we get the function's original name through, as well? |
236 | // | 234 | // |
237 | if (luaL_loadbuffer(L2, _s, _sz, fname) != 0) { // L2: ... {cache} ... p function | 235 | if (luaL_loadbuffer(L2, _bytecode.data(), _bytecode.size(), _fname) != 0) { // L2: ... {cache} ... p function |
238 | // chunk is precompiled so only LUA_ERRMEM can happen | 236 | // chunk is precompiled so only LUA_ERRMEM can happen |
239 | // "Otherwise, it pushes an error message" | 237 | // "Otherwise, it pushes an error message" |
240 | // | 238 | // |
241 | STACK_GROW(L1, 1); | 239 | STACK_GROW(L1, 1); |
242 | raise_luaL_error(getErrL(), "%s: %s", fname, lua_tostring(L2, -1)); | 240 | raise_luaL_error(getErrL(), "%s: %s", _fname, lua_tostring(L2, -1)); |
243 | } | 241 | } |
244 | // remove the dumped string | 242 | // remove the dumped string |
245 | lua_pop(L1, 1); // ... | 243 | lua_pop(L1, 1); // ... |
@@ -268,7 +266,7 @@ void InterCopyContext::copy_func() const | |||
268 | lua_pushglobaltable(L1); // L1: ... _G | 266 | lua_pushglobaltable(L1); // L1: ... _G |
269 | #endif // LUA_VERSION_NUM | 267 | #endif // LUA_VERSION_NUM |
270 | for (_n = 0; (_c.name = lua_getupvalue(L1, L1_i, 1 + _n)) != nullptr; ++_n) { // L1: ... _G up[n] | 268 | for (_n = 0; (_c.name = lua_getupvalue(L1, L1_i, 1 + _n)) != nullptr; ++_n) { // L1: ... _G up[n] |
271 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "UPNAME[%d]: %s -> " INDENT_END(U), n, _c.name)); | 269 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "UPNAME[%d]: %s -> " INDENT_END(U), _n, _c.name)); |
272 | #if LUA_VERSION_NUM >= 502 | 270 | #if LUA_VERSION_NUM >= 502 |
273 | if (lua_rawequal(L1, -1, -2)) { // is the upvalue equal to the global table? | 271 | if (lua_rawequal(L1, -1, -2)) { // is the upvalue equal to the global table? |
274 | DEBUGSPEW_CODE(fprintf(stderr, "pushing destination global scope\n")); | 272 | DEBUGSPEW_CODE(fprintf(stderr, "pushing destination global scope\n")); |
@@ -350,7 +348,7 @@ void InterCopyContext::lookup_native_func() const | |||
350 | "%s%s: function '%s' not found in %s destination transfer database.", | 348 | "%s%s: function '%s' not found in %s destination transfer database.", |
351 | lua_isnil(L2, -1) ? "" : "INTERNAL ERROR IN ", | 349 | lua_isnil(L2, -1) ? "" : "INTERNAL ERROR IN ", |
352 | _from ? _from : "main", | 350 | _from ? _from : "main", |
353 | _fqn, | 351 | _fqn.data(), |
354 | _to ? _to : "main"); | 352 | _to ? _to : "main"); |
355 | return; | 353 | return; |
356 | } | 354 | } |
@@ -499,47 +497,45 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
499 | // maybe offer this possibility as a global configuration option, or a linda setting, or as a parameter of the call causing the transfer? | 497 | // maybe offer this possibility as a global configuration option, or a linda setting, or as a parameter of the call causing the transfer? |
500 | } | 498 | } |
501 | 499 | ||
502 | char* valPath{ nullptr }; | 500 | char* _valPath{ nullptr }; |
503 | if (U->verboseErrors) { | 501 | if (U->verboseErrors) { |
504 | // for debug purposes, let's try to build a useful name | 502 | // for debug purposes, let's try to build a useful name |
505 | if (lua_type(L1, _key_i) == LUA_TSTRING) { | 503 | if (lua_type(L1, _key_i) == LUA_TSTRING) { |
506 | char const* key{ lua_tostring(L1, _key_i) }; | 504 | std::string_view const _key{ lua_tostringview(L1, _key_i) }; |
507 | size_t const keyRawLen = lua_rawlen(L1, _key_i); | 505 | size_t const _bufLen{ strlen(name) + _key.size() + 2 }; // +2 for separator dot and terminating 0 |
508 | size_t const bufLen = strlen(name) + keyRawLen + 2; | 506 | _valPath = static_cast<char*>(alloca(_bufLen)); |
509 | valPath = (char*) alloca(bufLen); | 507 | sprintf(_valPath, "%s.%*s", name, static_cast<int>(_key.size()), _key.data()); |
510 | sprintf(valPath, "%s.%*s", name, (int) keyRawLen, key); | ||
511 | key = nullptr; | ||
512 | } | 508 | } |
513 | #if defined LUA_LNUM || LUA_VERSION_NUM >= 503 | 509 | #if defined LUA_LNUM || LUA_VERSION_NUM >= 503 |
514 | else if (lua_isinteger(L1, _key_i)) { | 510 | else if (lua_isinteger(L1, _key_i)) { |
515 | lua_Integer const key{ lua_tointeger(L1, _key_i) }; | 511 | lua_Integer const key{ lua_tointeger(L1, _key_i) }; |
516 | valPath = (char*) alloca(strlen(name) + 32 + 3); | 512 | _valPath = (char*) alloca(strlen(name) + 32 + 3); // +3 for [] and terminating 0 |
517 | sprintf(valPath, "%s[" LUA_INTEGER_FMT "]", name, key); | 513 | sprintf(_valPath, "%s[" LUA_INTEGER_FMT "]", name, key); |
518 | } | 514 | } |
519 | #endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503 | 515 | #endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503 |
520 | else if (lua_type(L1, _key_i) == LUA_TNUMBER) { | 516 | else if (lua_type(L1, _key_i) == LUA_TNUMBER) { |
521 | lua_Number const key{ lua_tonumber(L1, _key_i) }; | 517 | lua_Number const key{ lua_tonumber(L1, _key_i) }; |
522 | valPath = (char*) alloca(strlen(name) + 32 + 3); | 518 | _valPath = (char*) alloca(strlen(name) + 32 + 3); // +3 for [] and terminating 0 |
523 | sprintf(valPath, "%s[" LUA_NUMBER_FMT "]", name, key); | 519 | sprintf(_valPath, "%s[" LUA_NUMBER_FMT "]", name, key); |
524 | } else if (lua_type(L1, _key_i) == LUA_TLIGHTUSERDATA) { | 520 | } else if (lua_type(L1, _key_i) == LUA_TLIGHTUSERDATA) { |
525 | void* const key{ lua_touserdata(L1, _key_i) }; | 521 | void* const key{ lua_touserdata(L1, _key_i) }; |
526 | valPath = (char*) alloca(strlen(name) + 16 + 5); | 522 | _valPath = (char*) alloca(strlen(name) + 16 + 5); // +5 for [U:] and terminating 0 |
527 | sprintf(valPath, "%s[U:%p]", name, key); | 523 | sprintf(_valPath, "%s[U:%p]", name, key); |
528 | } else if (lua_type(L1, _key_i) == LUA_TBOOLEAN) { | 524 | } else if (lua_type(L1, _key_i) == LUA_TBOOLEAN) { |
529 | int const key{ lua_toboolean(L1, _key_i) }; | 525 | int const key{ lua_toboolean(L1, _key_i) }; |
530 | valPath = (char*) alloca(strlen(name) + 8); | 526 | _valPath = (char*) alloca(strlen(name) + 8); // +8 for [], 'false' and terminating 0 |
531 | sprintf(valPath, "%s[%s]", name, key ? "true" : "false"); | 527 | sprintf(_valPath, "%s[%s]", name, key ? "true" : "false"); |
532 | } | 528 | } |
533 | } | 529 | } |
534 | _c.L1_i = SourceIndex{ _val_i }; | 530 | _c.L1_i = SourceIndex{ _val_i }; |
535 | // Contents of metatables are copied with cache checking. important to detect loops. | 531 | // Contents of metatables are copied with cache checking. important to detect loops. |
536 | _c.vt = VT::NORMAL; | 532 | _c.vt = VT::NORMAL; |
537 | _c.name = valPath ? valPath : name; | 533 | _c.name = _valPath ? _valPath : name; |
538 | if (_c.inter_copy_one()) { | 534 | if (_c.inter_copy_one()) { |
539 | LUA_ASSERT(L1, lua_istable(L2, -3)); | 535 | LUA_ASSERT(L1, lua_istable(L2, -3)); |
540 | lua_rawset(L2, -3); // add to table (pops key & val) | 536 | lua_rawset(L2, -3); // add to table (pops key & val) |
541 | } else { | 537 | } else { |
542 | raise_luaL_error(getErrL(), "Unable to copy %s entry '%s' because of value is of type '%s'", (vt == VT::NORMAL) ? "table" : "metatable", valPath, luaL_typename(L1, _val_i)); | 538 | raise_luaL_error(getErrL(), "Unable to copy %s entry '%s' because of value is of type '%s'", (vt == VT::NORMAL) ? "table" : "metatable", _valPath, luaL_typename(L1, _val_i)); |
543 | } | 539 | } |
544 | } | 540 | } |
545 | 541 | ||
@@ -931,10 +927,9 @@ void InterCopyContext::inter_copy_keyvaluepair() const | |||
931 | 927 | ||
932 | [[nodiscard]] bool InterCopyContext::inter_copy_string() const | 928 | [[nodiscard]] bool InterCopyContext::inter_copy_string() const |
933 | { | 929 | { |
934 | size_t _len{ 0 }; | 930 | std::string_view const _s{ lua_tostringview(L1, L1_i) }; |
935 | char const* const _s{ lua_tolstring(L1, L1_i, &_len) }; | 931 | DEBUGSPEW_CODE(fprintf(stderr, "'%s'\n", _s.data())); |
936 | DEBUGSPEW_CODE(fprintf(stderr, "'%s'\n", _s)); | 932 | lua_pushlstring(L2, _s.data(), _s.size()); |
937 | lua_pushlstring(L2, _s, _len); | ||
938 | return true; | 933 | return true; |
939 | } | 934 | } |
940 | 935 | ||
diff --git a/src/lanes.cpp b/src/lanes.cpp index a68c3aa..74e2507 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
@@ -395,9 +395,8 @@ LUAG_FUNC(lane_new) | |||
395 | raise_luaL_error(L_, "required module list should be a list of strings"); | 395 | raise_luaL_error(L_, "required module list should be a list of strings"); |
396 | } else { | 396 | } else { |
397 | // require the module in the target state, and populate the lookup table there too | 397 | // require the module in the target state, and populate the lookup table there too |
398 | size_t _len{ 0 }; | 398 | std::string_view const _name{ lua_tostringview(L_, -1) }; |
399 | char const* _name{ lua_tolstring(L_, -1, &_len) }; | 399 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: require '%s'\n" INDENT_END(_U), _name.data())); |
400 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: require '%s'\n" INDENT_END(_U), name)); | ||
401 | 400 | ||
402 | // require the module in the target lane | 401 | // require the module in the target lane |
403 | lua_getglobal(_L2, "require"); // L_: [fixed] args... n "modname" L2: require()? | 402 | lua_getglobal(_L2, "require"); // L_: [fixed] args... n "modname" L2: require()? |
@@ -405,7 +404,7 @@ LUAG_FUNC(lane_new) | |||
405 | lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2: | 404 | lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2: |
406 | raise_luaL_error(L_, "cannot pre-require modules without loading 'package' library first"); | 405 | raise_luaL_error(L_, "cannot pre-require modules without loading 'package' library first"); |
407 | } else { | 406 | } else { |
408 | lua_pushlstring(_L2, _name, _len); // L_: [fixed] args... n "modname" L2: require() name | 407 | lua_pushlstring(_L2, _name.data(), _name.size()); // L_: [fixed] args... n "modname" L2: require() name |
409 | LuaError const _rc{ lua_pcall(_L2, 1, 1, 0) }; // L_: [fixed] args... n "modname" L2: ret/errcode | 408 | LuaError const _rc{ lua_pcall(_L2, 1, 1, 0) }; // L_: [fixed] args... n "modname" L2: ret/errcode |
410 | if (_rc != LuaError::OK) { | 409 | if (_rc != LuaError::OK) { |
411 | // propagate error to main state if any | 410 | // propagate error to main state if any |
@@ -415,7 +414,7 @@ LUAG_FUNC(lane_new) | |||
415 | } | 414 | } |
416 | // here the module was successfully required // L_: [fixed] args... n "modname" L2: ret | 415 | // here the module was successfully required // L_: [fixed] args... n "modname" L2: ret |
417 | // after requiring the module, register the functions it exported in our name<->function database | 416 | // after requiring the module, register the functions it exported in our name<->function database |
418 | populate_func_lookup_table(_L2, -1, _name); | 417 | populate_func_lookup_table(_L2, -1, _name.data()); |
419 | lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2: | 418 | lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2: |
420 | } | 419 | } |
421 | } | 420 | } |
diff --git a/src/lindafactory.cpp b/src/lindafactory.cpp index 9bc56d9..015baf4 100644 --- a/src/lindafactory.cpp +++ b/src/lindafactory.cpp | |||
@@ -103,8 +103,7 @@ std::string_view LindaFactory::moduleName() const | |||
103 | 103 | ||
104 | DeepPrelude* LindaFactory::newDeepObjectInternal(lua_State* L_) const | 104 | DeepPrelude* LindaFactory::newDeepObjectInternal(lua_State* L_) const |
105 | { | 105 | { |
106 | size_t _name_len{ 0 }; | 106 | std::string_view _linda_name{}; |
107 | char const* _linda_name{ nullptr }; | ||
108 | LindaGroup _linda_group{ 0 }; | 107 | LindaGroup _linda_group{ 0 }; |
109 | // should have a string and/or a number of the stack as parameters (name and group) | 108 | // should have a string and/or a number of the stack as parameters (name and group) |
110 | switch (lua_gettop(L_)) { | 109 | switch (lua_gettop(L_)) { |
@@ -113,14 +112,14 @@ DeepPrelude* LindaFactory::newDeepObjectInternal(lua_State* L_) const | |||
113 | 112 | ||
114 | case 1: // 1 parameter, either a name or a group | 113 | case 1: // 1 parameter, either a name or a group |
115 | if (lua_type(L_, -1) == LUA_TSTRING) { | 114 | if (lua_type(L_, -1) == LUA_TSTRING) { |
116 | _linda_name = lua_tolstring(L_, -1, &_name_len); | 115 | _linda_name = lua_tostringview(L_, -1); |
117 | } else { | 116 | } else { |
118 | _linda_group = LindaGroup{ static_cast<int>(lua_tointeger(L_, -1)) }; | 117 | _linda_group = LindaGroup{ static_cast<int>(lua_tointeger(L_, -1)) }; |
119 | } | 118 | } |
120 | break; | 119 | break; |
121 | 120 | ||
122 | case 2: // 2 parameters, a name and group, in that order | 121 | case 2: // 2 parameters, a name and group, in that order |
123 | _linda_name = lua_tolstring(L_, -2, &_name_len); | 122 | _linda_name = lua_tostringview(L_, -2); |
124 | _linda_group = LindaGroup{ static_cast<int>(lua_tointeger(L_, -1)) }; | 123 | _linda_group = LindaGroup{ static_cast<int>(lua_tointeger(L_, -1)) }; |
125 | break; | 124 | break; |
126 | } | 125 | } |
@@ -128,6 +127,6 @@ DeepPrelude* LindaFactory::newDeepObjectInternal(lua_State* L_) const | |||
128 | // The deep data is allocated separately of Lua stack; we might no longer be around when last reference to it is being released. | 127 | // The deep data is allocated separately of Lua stack; we might no longer be around when last reference to it is being released. |
129 | // One can use any memory allocation scheme. Just don't use L's allocF because we don't know which state will get the honor of GCing the linda | 128 | // One can use any memory allocation scheme. Just don't use L's allocF because we don't know which state will get the honor of GCing the linda |
130 | Universe* const _U{ universe_get(L_) }; | 129 | Universe* const _U{ universe_get(L_) }; |
131 | Linda* const _linda{ new (_U) Linda{ _U, _linda_group, _linda_name, _name_len } }; | 130 | Linda* const _linda{ new (_U) Linda{ _U, _linda_group, _linda_name.data(), _linda_name.size() } }; |
132 | return _linda; | 131 | return _linda; |
133 | } | 132 | } |
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 |
diff --git a/src/universe.cpp b/src/universe.cpp index 9ab1290..52aa368 100644 --- a/src/universe.cpp +++ b/src/universe.cpp | |||
@@ -368,14 +368,14 @@ void Universe::terminateFreeRunningLanes(lua_State* L_, lua_Duration shutdownTim | |||
368 | int universe_gc(lua_State* L_) | 368 | int universe_gc(lua_State* L_) |
369 | { | 369 | { |
370 | lua_Duration const _shutdown_timeout{ lua_tonumber(L_, lua_upvalueindex(1)) }; | 370 | lua_Duration const _shutdown_timeout{ lua_tonumber(L_, lua_upvalueindex(1)) }; |
371 | [[maybe_unused]] char const* const _op_string{ lua_tostring(L_, lua_upvalueindex(2)) }; | 371 | std::string_view const _op_string{ lua_tostringview(L_, lua_upvalueindex(2)) }; |
372 | Universe* const _U{ lua_tofulluserdata<Universe>(L_, 1) }; | 372 | Universe* const _U{ lua_tofulluserdata<Universe>(L_, 1) }; |
373 | _U->terminateFreeRunningLanes(L_, _shutdown_timeout, which_cancel_op(_op_string)); | 373 | _U->terminateFreeRunningLanes(L_, _shutdown_timeout, which_cancel_op(_op_string)); |
374 | 374 | ||
375 | // no need to mutex-protect this as all threads in the universe are gone at that point | 375 | // no need to mutex-protect this as all threads in the universe are gone at that point |
376 | if (_U->timerLinda != nullptr) { // test in case some early internal error prevented Lanes from creating the deep timer | 376 | if (_U->timerLinda != nullptr) { // test in case some early internal error prevented Lanes from creating the deep timer |
377 | [[maybe_unused]] int const prev_ref_count{ _U->timerLinda->refcount.fetch_sub(1, std::memory_order_relaxed) }; | 377 | [[maybe_unused]] int const _prev_ref_count{ _U->timerLinda->refcount.fetch_sub(1, std::memory_order_relaxed) }; |
378 | LUA_ASSERT(L_, prev_ref_count == 1); // this should be the last reference | 378 | LUA_ASSERT(L_, _prev_ref_count == 1); // this should be the last reference |
379 | DeepFactory::DeleteDeepObject(L_, _U->timerLinda); | 379 | DeepFactory::DeleteDeepObject(L_, _U->timerLinda); |
380 | _U->timerLinda = nullptr; | 380 | _U->timerLinda = nullptr; |
381 | } | 381 | } |