From 998e225490cb78b94c1db1d2e16a8ad4dfae83ec Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 28 Apr 2025 19:14:27 +0200 Subject: [PATCH] Clean-up: reimplement the SeachPathSplitter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ...to be more compliant to the »Lumiera Forward Iterator« concept. This can be easily achieved by inheriting from util::RegexSearchIter, similar to the example in CSV.hpp Regarding #896, I changed the string rendering to use fs::path::generic_string where appropriate, which means that we're using the normalised path rendering --- src/common/basic-setup.cpp | 2 +- src/common/configfacade.cpp | 19 ++++------- src/lib/searchpath.cpp | 25 ++++++++------ src/lib/searchpath.hpp | 38 +++++++++------------ src/lib/test/test-helper.hpp | 8 ++++- src/stage/workspace/ui-style.cpp | 6 ++-- tests/15library.tests | 22 ++++++------ tests/library/search-path-splitter-test.cpp | 32 ++++++++++------- wiki/thinkPad.ichthyo.mm | 29 ++++++++++------ 9 files changed, 97 insertions(+), 84 deletions(-) diff --git a/src/common/basic-setup.cpp b/src/common/basic-setup.cpp index dd3952d9c..3a1850c56 100644 --- a/src/common/basic-setup.cpp +++ b/src/common/basic-setup.cpp @@ -54,7 +54,7 @@ namespace lumiera { string resolve (fs::path iniSpec) { - string searchpath = iniSpec.parent_path().string(); ///////////TICKET #896 + string searchpath = iniSpec.parent_path().generic_string(); return resolveModulePath (iniSpec.filename(), searchpath); } diff --git a/src/common/configfacade.cpp b/src/common/configfacade.cpp index fbb818826..d5a4fd121 100644 --- a/src/common/configfacade.cpp +++ b/src/common/configfacade.cpp @@ -35,6 +35,8 @@ #include "include/config-facade.h" #include "common/appstate.hpp" #include "lib/searchpath.hpp" +#include "lib/iter-explorer.hpp" +#include "lib/format-util.hpp" #include "lib/util.hpp" extern "C" { @@ -130,18 +132,11 @@ extern "C" { /* ==== implementation C interface for accessing setup.ini ======= const char* lumiera_get_plugin_path_default () - { - static string pathSpec; - if (isnil (pathSpec)) - { - pathSpec += "plugin.path="; // syntax expected by lumiera_config_setdefault - - // fetch plugin search path from setup.ini and expand any $ORIGIN token - SearchPathSplitter pathElement(Config::get (KEY_PLUGIN_PATH)); - while (pathElement) - pathSpec += pathElement.next() +":"; - } - + { // Meyer's Singleton... + static string pathSpec = []{ string pluginPath = Config::get (KEY_PLUGIN_PATH); + return "plugin.path=" // syntax expected by lumiera_config_setdefault + + util::join (SearchPathSplitter{pluginPath}, ":"); + }(); return cStr(pathSpec); } } diff --git a/src/lib/searchpath.cpp b/src/lib/searchpath.cpp index 9b1bdd948..f6def1bc7 100644 --- a/src/lib/searchpath.cpp +++ b/src/lib/searchpath.cpp @@ -19,6 +19,7 @@ #include "lib/error.hpp" #include "lib/searchpath.hpp" +#include "lib/format-string.hpp" #include "lib/symbol.hpp" @@ -31,10 +32,11 @@ namespace lib { + using util::_Fmt; using std::regex; using std::regex_replace; - const regex SearchPathSplitter::EXTRACT_PATHSPEC ("[^:]+"); + const regex SearchPathSplitter::ACCEPT_PATHELEMENT{"(^|:)\\s*([^:]+)", regex::optimize}; /** @internal helper to figure out the installation directory, @@ -57,9 +59,9 @@ namespace lib { string replaceMagicLinkerTokens (string const& src) { - static const regex PICK_ORIGIN_TOKEN ("\\$?ORIGIN/?"); + static const regex PICK_ORIGIN_TOKEN{"\\$?ORIGIN/?", regex::optimize}; static const string expandedOriginDir - = findExePath().parent_path().string() + "/"; ///////////TICKET #896 + = findExePath().parent_path().generic_string() + "/"; return regex_replace (src, PICK_ORIGIN_TOKEN, expandedOriginDir); } @@ -72,20 +74,21 @@ namespace lib { resolveModulePath (fs::path moduleName, string searchPath) { fs::path modulePathName (moduleName); - SearchPathSplitter searchLocation(searchPath); ///////////TICKET #896 + SearchPathSplitter searchLocation(searchPath); while (not fs::exists (modulePathName)) { // try / continue search path - if (searchLocation.isValid()) - modulePathName = fs::path() / searchLocation.next() / moduleName; - else - throw error::Config ("Module \""+moduleName.string()+"\" not found" /////TICKET #896 - + (searchPath.empty()? ".":" in search path: "+searchPath)); + if (not searchLocation) + throw error::Config{_Fmt{"Module %s not found%s"} + % moduleName + %(searchPath.empty()? ".":" in search path: "+searchPath)}; + modulePathName = *searchLocation / moduleName; + ++searchLocation; } - TRACE (config, "found module %s", modulePathName.string().c_str()); - return modulePathName.string(); ///////////TICKET #896 + TRACE (config, "found module %s", cStr(modulePathName.generic_string())); + return modulePathName.generic_string(); } diff --git a/src/lib/searchpath.hpp b/src/lib/searchpath.hpp index af0e5c8d5..7e0264990 100644 --- a/src/lib/searchpath.hpp +++ b/src/lib/searchpath.hpp @@ -30,6 +30,7 @@ #include "lib/file.hpp" #include +#include namespace lib { @@ -56,42 +57,35 @@ namespace lib { * This iterator class dissects a ':'-separated path list. The individual * components may use the symbol \c $ORIGIN to refer to the directory * holding the current executable. - * @note #next picks the current component and advances the iteration. */ class SearchPathSplitter - : util::NonCopyable + : public util::RegexSearchIter { - string pathSpec_; - std::sregex_iterator pos_, - end_; - - static const std::regex EXTRACT_PATHSPEC; + static const regex ACCEPT_PATHELEMENT; public: - SearchPathSplitter (string const& searchPath) - : pathSpec_(replaceMagicLinkerTokens (searchPath)) - , pos_(pathSpec_.begin(),pathSpec_.end(), EXTRACT_PATHSPEC) - , end_() + SearchPathSplitter() = default; + SearchPathSplitter (string& searchPath) ///< @warning search path string must exist somewhere else + : RegexSearchIter{searchPath, ACCEPT_PATHELEMENT} { } - explicit operator bool() const { return isValid(); } + LIFT_PARENT_INCREMENT_OPERATOR (std::sregex_iterator); + ENABLE_USE_IN_STD_RANGE_FOR_LOOPS (SearchPathSplitter); - bool - isValid() const - { - return pos_ != end_; - } + using value_type = std::string; + using reference = value_type&; + using pointer = value_type*; string - next () + operator*() const { if (!isValid()) throw error::Logic ("Search path exhausted." ,LERR_(ITER_EXHAUST)); - string currentPathElement = pos_->str(); - ++pos_; - return currentPathElement; + string pathElm = util::RegexSearchIter::operator*()[2]; + pathElm = boost::algorithm::trim_right_copy(pathElm); + return replaceMagicLinkerTokens (pathElm); } }; @@ -103,7 +97,7 @@ namespace lib { * SearchPathSplitter, until encountering an existing file with the * given name. * @return the absolute pathname of the module file found - * @throws error::Config when the resolution fails + * @throws error::Config when the resolution fails */ string resolveModulePath (fs::path moduleName, string searchPath = ""); diff --git a/src/lib/test/test-helper.hpp b/src/lib/test/test-helper.hpp index 0b14d164c..e55922f3b 100644 --- a/src/lib/test/test-helper.hpp +++ b/src/lib/test/test-helper.hpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -49,7 +50,7 @@ namespace lib { namespace test{ - + using lib::Literal; using std::string; using lib::rani; @@ -327,8 +328,13 @@ namespace test{ class ExpectString : public std::string { + public: using std::string::string; + ExpectString(std::string && s) : std::string{std::move(s)}{ } + ExpectString(std::string const& s) : std::string{s} { } + + template friend bool operator== (X const& x, ExpectString const& expected) diff --git a/src/stage/workspace/ui-style.cpp b/src/stage/workspace/ui-style.cpp index 0c3c296a1..3ea13f26d 100644 --- a/src/stage/workspace/ui-style.cpp +++ b/src/stage/workspace/ui-style.cpp @@ -262,10 +262,10 @@ namespace workspace { return true; // Try to resolve the icon via the configured search path - lib::SearchPathSplitter iconLocations (iconSearchPath_); - while (iconLocations) + lib::SearchPathSplitter iconLocations{iconSearchPath_}; + for (auto const& location : iconLocations) if (addNonThemeIconSource (icon_set - ,iconLocations.next() + ,location ,icon_name ,size ,wildcard)) diff --git a/tests/15library.tests b/tests/15library.tests index ae3bc8571..86331a4b5 100644 --- a/tests/15library.tests +++ b/tests/15library.tests @@ -624,17 +624,17 @@ END TEST "Search path walking" SearchPathSplitter_test < - - + @@ -161391,8 +161390,8 @@ Since then others have made contributions, see the log for the history. - - + + @@ -161439,19 +161438,29 @@ Since then others have made contributions, see the log for the history. - - + + + + + + +

- ...das war vermutlich mein erster Versuch, eine Iterator-Klasse in C++ zu bauen. + ...das war vermutlich mein erster Versuch, eine Iterator-Klasse in C++ zu bauen — hatte mich dabei offensichtlich an Java orientiert

-
+ + + + + + + + - -