From e1af4f31a1916a18d6ee0744bd91c1ee9d8651f4 Mon Sep 17 00:00:00 2001
From: Benoit Germain
Date: Tue, 24 Sep 2024 10:33:20 +0200
Subject: Modernized lanes.gen() base library list processing code
---
docs/index.html | 4 +++-
src/state.cpp | 36 ++++++++++++++++++++++--------------
2 files changed, 25 insertions(+), 15 deletions(-)
diff --git a/docs/index.html b/docs/index.html
index 79b33f1..dc159f4 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -70,7 +70,7 @@
- This document was revised on 12-Jun-24, and applies to version 4.0.0.
+ This document was revised on 24-Sep-24, and applies to version 4.0.0.
@@ -681,6 +681,7 @@
Any non-nil value causes initialization of "base" and "jit" (the latter only for LuaJIT-based builds).
+ Trying to load a library not supported by the running Lua flavor will raise an error, unless the library name is postfixed with a '?'.
Initializing the standard libs takes a bit of time at each lane invocation. This is the main reason why "no libraries" is the default.
@@ -716,6 +717,7 @@
These tables are built from the modules listed here. required must be an array of strings, each one being the name of a module to be required. Each module is required with require() before the lanes function is invoked.
So, from the required module's point of view, requiring it manually from inside the lane body or having it required this way doesn't change anything. From the lane body's point of view, the only difference is that a module not creating a global won't be accessible.
Therefore, a lane body will also have to require a module manually, but this won't do anything more (see Lua's require documentation).
+ Module names may contain characters matching std::isalnum(c_) || c_ == '.' || c_ == '-' || c_ == '_'. Anything else is considered a valid name separator.
ATTEMPTING TO TRANSFER A FUNCTION REGISTERED BY A MODULE NOT LISTED HERE WILL RAISE AN ERROR.
diff --git a/src/state.cpp b/src/state.cpp
index 322def8..aa6e6a9 100644
--- a/src/state.cpp
+++ b/src/state.cpp
@@ -247,21 +247,29 @@ namespace state {
STACK_CHECK(_L, 0);
// scan all libraries, open them one by one
- if (!_libs.empty()) {
- unsigned int _len{ 0 };
- for (char const* _p{ _libs.data() }; *_p; _p += _len) {
- // skip delimiters ('.' can be part of name for "lanes.core")
- while (*_p && !std::isalnum(*_p) && *_p != '.') {
- ++_p;
- }
- // skip name
- _len = 0;
- while (std::isalnum(_p[_len]) || _p[_len] == '.') {
- ++_len;
- }
- // open library
- Open1Lib(_L, { _p, _len });
+ auto isLibNameChar = [](char const c_) {
+ // '.' can be part of name for "lanes.core"
+ return std::isalnum(c_) || c_ == '.' || c_ == '-' || c_ == '_';
+ };
+ while (!_libs.empty()) {
+ // remove prefix not part of a name
+ auto _nameStart{ std::find_if(std::cbegin(_libs), std::cend(_libs), isLibNameChar) };
+ if (_nameStart == _libs.end()) {
+ break;
+ }
+ auto const _prefixLen{ std::distance(_libs.begin(), _nameStart) };
+
+ auto const _nameEnd{ std::find_if(_nameStart, std::cend(_libs), [&isLibNameChar](char const _c) { return !isLibNameChar(_c); }) };
+ // advance to the end of the character sequence composing the name
+ auto const _nameLen{ std::distance(_nameStart, _nameEnd) };
+ if (_nameLen == 0) {
+ break;
}
+ // open library
+ std::string_view const _libName{ _libs.substr(_prefixLen, _nameLen) };
+ Open1Lib(_L, _libName);
+ // advance to next item (can't do this earlier as it invalidates iterators)
+ _libs.remove_prefix(_prefixLen + _nameLen);
}
lua_gc(_L, LUA_GCRESTART, 0);
--
cgit v1.2.3-55-g6feb