diff --git a/examples/example.cpp b/examples/example.cpp index bcb373b..f29d035 100644 --- a/examples/example.cpp +++ b/examples/example.cpp @@ -84,8 +84,8 @@ int main(int /*argc*/, char** /*argv*/) // NOLINT { // Create and configure the plugin loader to be able to find libraries in which plugins exist PluginLoader loader; - loader.search_paths.insert(PLUGIN_DIR); - loader.search_libraries.insert(PLUGINS); + loader.search_paths.emplace_back(PLUGIN_DIR); + loader.search_libraries.emplace_back(PLUGINS); // Printer plugins demoPrinterPlugins(loader); diff --git a/include/boost_plugin_loader/fwd.h b/include/boost_plugin_loader/fwd.h index f66a3cd..2280999 100644 --- a/include/boost_plugin_loader/fwd.h +++ b/include/boost_plugin_loader/fwd.h @@ -22,6 +22,6 @@ namespace boost_plugin_loader { class PluginLoader; -} +} // namespace boost_plugin_loader #endif // BOOST_PLUGIN_LOADER_FWD_H diff --git a/include/boost_plugin_loader/plugin_loader.h b/include/boost_plugin_loader/plugin_loader.h index e017972..36d0f28 100644 --- a/include/boost_plugin_loader/plugin_loader.h +++ b/include/boost_plugin_loader/plugin_loader.h @@ -20,7 +20,6 @@ #define BOOST_PLUGIN_LOADER_PLUGIN_LOADER_H // STD -#include #include #include #include @@ -37,6 +36,7 @@ class shared_library; namespace boost_plugin_loader { + /** @brief Used to test for getSection method for getAvailablePlugins */ template struct has_getSection @@ -79,10 +79,10 @@ class PluginLoader bool search_system_folders{ true }; /** @brief A list of paths to search for plugins */ - std::set search_paths; + std::vector search_paths; /** @brief A list of library names without the prefix or suffix that contain plugins*/ - std::set search_libraries; + std::vector search_libraries; /** @brief The environment variable containing plugin search paths */ std::string search_paths_env; @@ -149,18 +149,18 @@ class PluginLoader protected: template void reportErrorCommon(std::ostream& msg, const std::string& plugin_name, bool search_system_folders, - const std::set& search_paths, - const std::set& search_libraries) const; + const std::vector& search_paths, + const std::vector& search_libraries) const; template typename std::enable_if_t::value, void> reportError(std::ostream& msg, const std::string& plugin_name, bool search_system_folders, - const std::set& search_paths, const std::set& search_libraries) const; + const std::vector& search_paths, const std::vector& search_libraries) const; template typename std::enable_if_t::value, void> reportError(std::ostream& msg, const std::string& plugin_name, bool search_system_folders, - const std::set& search_paths, const std::set& search_libraries) const; + const std::vector& search_paths, const std::vector& search_libraries) const; /** * @brief Checks if the library has the input symbol name, given that the plugin class does not define a section name diff --git a/include/boost_plugin_loader/plugin_loader.hpp b/include/boost_plugin_loader/plugin_loader.hpp index 8421979..819f736 100644 --- a/include/boost_plugin_loader/plugin_loader.hpp +++ b/include/boost_plugin_loader/plugin_loader.hpp @@ -96,8 +96,8 @@ PluginLoader::hasSymbol(const boost::dll::shared_library& lib, const std::string * Libraries specified with absolute paths will be returned first in the list before libraries found in local paths (but * in no particular order in at the front of the list). */ -static std::vector loadLibraries(const std::set& library_names, - const std::set& search_paths_local, +static std::vector loadLibraries(const std::vector& library_names, + const std::vector& search_paths_local, const bool search_system_folders) { std::vector libraries; @@ -157,8 +157,8 @@ static std::vector loadLibraries(const std::set void PluginLoader::reportErrorCommon(std::ostream& msg, const std::string& plugin_name, bool search_system_folders, - const std::set& search_paths, - const std::set& search_libraries) const + const std::vector& search_paths, + const std::vector& search_libraries) const { const std::string plugin_base_type = boost::core::demangle(typeid(PluginBase).name()); msg << "Failed to create plugin instance '" << plugin_name << "' of type '" << plugin_base_type << "'\n"; @@ -176,8 +176,8 @@ void PluginLoader::reportErrorCommon(std::ostream& msg, const std::string& plugi template typename std::enable_if_t::value, void> PluginLoader::reportError(std::ostream& msg, const std::string& plugin_name, bool search_system_folders, - const std::set& search_paths, - const std::set& search_libraries) const + const std::vector& search_paths, + const std::vector& search_libraries) const { return reportErrorCommon(msg, plugin_name, search_system_folders, search_paths, search_libraries); } @@ -185,8 +185,8 @@ PluginLoader::reportError(std::ostream& msg, const std::string& plugin_name, boo template typename std::enable_if_t::value, void> PluginLoader::reportError(std::ostream& msg, const std::string& plugin_name, bool search_system_folders, - const std::set& search_paths, - const std::set& search_libraries) const + const std::vector& search_paths, + const std::vector& search_libraries) const { reportErrorCommon(msg, plugin_name, search_system_folders, search_paths, search_libraries); @@ -202,12 +202,12 @@ template std::shared_ptr PluginLoader::createInstance(const std::string& plugin_name) const { // Check for environment variable for plugin definitions - const std::set library_names = getAllLibraryNames(search_libraries_env, search_libraries); + const std::vector library_names = getAllLibraryNames(search_libraries_env, search_libraries); if (library_names.empty()) throw PluginLoaderException("No plugin libraries were provided!"); // Check for environment variable for search paths - const std::set search_paths_local = getAllSearchPaths(search_paths_env, search_paths); + const std::vector search_paths_local = getAllSearchPaths(search_paths_env, search_paths); // Load the libraries const std::vector libraries = @@ -228,12 +228,12 @@ std::shared_ptr PluginLoader::createInstance(const std::string& plug bool PluginLoader::isPluginAvailable(const std::string& plugin_name) const { // Check for environment variable for plugin definitions - const std::set library_names = getAllLibraryNames(search_libraries_env, search_libraries); + const std::vector library_names = getAllLibraryNames(search_libraries_env, search_libraries); if (library_names.empty()) throw PluginLoaderException("No plugin libraries were provided!"); // Check for environment variable for search paths - const std::set search_paths_local = getAllSearchPaths(search_paths_env, search_paths); + const std::vector search_paths_local = getAllSearchPaths(search_paths_env, search_paths); // Load the libraries const std::vector libraries = @@ -253,12 +253,12 @@ PluginLoader::getAvailablePlugins() const std::vector PluginLoader::getAvailablePlugins(const std::string& section) const { // Check for environment variable for plugin definitions - const std::set library_names = getAllLibraryNames(search_libraries_env, search_libraries); + const std::vector library_names = getAllLibraryNames(search_libraries_env, search_libraries); if (library_names.empty()) throw PluginLoaderException("No plugin libraries were provided!"); // Check for environment variable for search paths - const std::set search_paths_local = getAllSearchPaths(search_paths_env, search_paths); + const std::vector search_paths_local = getAllSearchPaths(search_paths_env, search_paths); // Load the libraries const std::vector libraries = @@ -278,12 +278,12 @@ std::vector PluginLoader::getAvailablePlugins(const std::string& se std::vector PluginLoader::getAvailableSections(bool include_hidden) const { // Check for environment variable for plugin definitions - const std::set library_names = getAllLibraryNames(search_libraries_env, search_libraries); + const std::vector library_names = getAllLibraryNames(search_libraries_env, search_libraries); if (library_names.empty()) throw PluginLoaderException("No plugin libraries were provided!"); // Check for environment variable for search paths - const std::set search_paths_local = getAllSearchPaths(search_paths_env, search_paths); + const std::vector search_paths_local = getAllSearchPaths(search_paths_env, search_paths); // Load the libraries const std::vector libraries = diff --git a/include/boost_plugin_loader/utils.h b/include/boost_plugin_loader/utils.h index 0a928f2..fb80f43 100644 --- a/include/boost_plugin_loader/utils.h +++ b/include/boost_plugin_loader/utils.h @@ -22,7 +22,6 @@ // STD #include #include -#include #include // Boost @@ -30,6 +29,7 @@ namespace boost_plugin_loader { + /** @brief The Boost Plugin Loader Exception class */ class PluginLoaderException : public std::runtime_error { @@ -83,7 +83,7 @@ std::string decorate(const std::string& library_name, const std::string& library * @param env_variable The environment variable name to extract list from * @return A list extracted from variable name */ -std::set parseEnvironmentVariableList(const std::string& env_variable); +std::vector parseEnvironmentVariableList(const std::string& env_variable); /** * @brief Get all available search paths @@ -91,8 +91,8 @@ std::set parseEnvironmentVariableList(const std::string& env_variab * @param existing_search_libraries A list of existing search paths * @return A list of search paths */ -std::set getAllSearchPaths(const std::string& search_paths_env, - const std::set& existing_search_paths); +std::vector getAllSearchPaths(const std::string& search_paths_env, + const std::vector& existing_search_paths); /** * @brief Get all available library names @@ -100,8 +100,8 @@ std::set getAllSearchPaths(const std::string& search_paths_env, * @param existing_search_libraries A list of existing library names without the prefix or suffix that contain plugins * @return A list of library names without the prefix or suffix that contain plugins */ -std::set getAllLibraryNames(const std::string& search_libraries_env, - const std::set& existing_search_libraries); +std::vector getAllLibraryNames(const std::string& search_libraries_env, + const std::vector& existing_search_libraries); /** * @brief Utility function to add library containing symbol to the search env variable diff --git a/src/utils.cpp b/src/utils.cpp index c74586c..5ee4f45 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -32,7 +32,6 @@ // STD #include #include -#include #include #include #include @@ -117,44 +116,47 @@ std::string decorate(const std::string& library_name, const std::string& library return actual_path.string(); } -std::set parseEnvironmentVariableList(const std::string& env_variable) +std::vector parseEnvironmentVariableList(const std::string& env_variable) { - std::set list; char* env_var = std::getenv(env_variable.c_str()); if (env_var == nullptr) // Environment variable not found - return list; + return {}; std::string evn_str = std::string(env_var); + std::vector env_list; #ifndef _WIN32 - boost::split(list, evn_str, boost::is_any_of(":"), boost::token_compress_on); + boost::split(env_list, evn_str, boost::is_any_of(":"), boost::token_compress_on); #else - boost::split(list, evn_str, boost::is_any_of(";"), boost::token_compress_on); + boost::split(env_list, evn_str, boost::is_any_of(";"), boost::token_compress_on); #endif + + std::vector list; + list.insert(list.end(), env_list.begin(), env_list.end()); return list; } -std::set getAllSearchPaths(const std::string& search_paths_env, - const std::set& existing_search_paths) +std::vector getAllSearchPaths(const std::string& search_paths_env, + const std::vector& existing_search_paths) { // Check for environment variable to override default library if (!search_paths_env.empty()) { - std::set search_paths = parseEnvironmentVariableList(search_paths_env); - search_paths.insert(existing_search_paths.begin(), existing_search_paths.end()); + std::vector search_paths = parseEnvironmentVariableList(search_paths_env); + search_paths.insert(search_paths.end(), existing_search_paths.begin(), existing_search_paths.end()); return search_paths; } return existing_search_paths; } -std::set getAllLibraryNames(const std::string& search_libraries_env, - const std::set& existing_search_libraries) +std::vector getAllLibraryNames(const std::string& search_libraries_env, + const std::vector& existing_search_libraries) { // Check for environment variable to override default library if (!search_libraries_env.empty()) { - std::set search_libraries = parseEnvironmentVariableList(search_libraries_env); - search_libraries.insert(existing_search_libraries.begin(), existing_search_libraries.end()); + std::vector search_libraries = parseEnvironmentVariableList(search_libraries_env); + search_libraries.insert(search_libraries.end(), existing_search_libraries.begin(), existing_search_libraries.end()); return search_libraries; } diff --git a/test/plugin_loader_unit.cpp b/test/plugin_loader_unit.cpp index d738c2a..ebd361e 100644 --- a/test/plugin_loader_unit.cpp +++ b/test/plugin_loader_unit.cpp @@ -25,7 +25,11 @@ #include #include #include +#include #include // NOLINT(misc-include-cleaner) +#include +#include +using namespace std::chrono_literals; // Boost #include @@ -46,55 +50,54 @@ TEST(BoostPluginLoaderUnit, Utils) // NOLINT { #ifndef _WIN32 - std::string env_var = "UNITTESTENV=a:b:c"; + std::string env_var = "UNITTESTENV=c:b:a"; #else - std::string env_var = "UNITTESTENV=a;b;c"; + std::string env_var = "UNITTESTENV=c;b;a"; #endif putenv(env_var.data()); // NOLINT(misc-include-cleaner) - std::set s = parseEnvironmentVariableList("UNITTESTENV"); - std::vector v(s.begin(), s.end()); - EXPECT_EQ(v[0], "a"); + std::vector v = parseEnvironmentVariableList("UNITTESTENV"); + EXPECT_EQ(v[0], "c"); EXPECT_EQ(v[1], "b"); - EXPECT_EQ(v[2], "c"); + EXPECT_EQ(v[2], "a"); - s = parseEnvironmentVariableList("does_not_exist"); - EXPECT_TRUE(s.empty()); + v = parseEnvironmentVariableList("does_not_exist"); + EXPECT_TRUE(v.empty()); } { // Test getAllSearchPaths #ifndef _WIN32 - std::string env_var = "UNITTESTENV=a:b:c"; + std::string env_var = "UNITTESTENV=c:b:a"; #else - std::string env_var = "UNITTESTENV=a;b;c"; + std::string env_var = "UNITTESTENV=c;b;a"; #endif putenv(env_var.data()); // NOLINT(misc-include-cleaner) std::string search_paths_env = "UNITTESTENV"; - std::set existing_search_paths; - std::set s = getAllSearchPaths(search_paths_env, existing_search_paths); + std::vector existing_search_paths; + std::vector s = getAllSearchPaths(search_paths_env, existing_search_paths); EXPECT_EQ(s.size(), 3); search_paths_env.clear(); s = getAllSearchPaths(search_paths_env, existing_search_paths); EXPECT_TRUE(s.empty()); - existing_search_paths = { "d", "e" }; + existing_search_paths.insert(existing_search_paths.end(), { "d", "e" }); s = getAllSearchPaths(search_paths_env, existing_search_paths); EXPECT_EQ(s.size(), 2); } { // Test getAllLibraryNames #ifndef _WIN32 - std::string env_var = "UNITTESTENV=a:b:c"; + std::string env_var = "UNITTESTENV=c:b:a"; #else - std::string env_var = "UNITTESTENV=a;b;c"; + std::string env_var = "UNITTESTENV=c;b;a"; #endif putenv(env_var.data()); // NOLINT(misc-include-cleaner) std::string search_paths_env = "UNITTESTENV"; - std::set existing_search_paths; - std::set s = getAllLibraryNames(search_paths_env, existing_search_paths); + std::vector existing_search_paths; + std::vector s = getAllLibraryNames(search_paths_env, existing_search_paths); EXPECT_EQ(s.size(), 3); search_paths_env.clear(); s = getAllSearchPaths(search_paths_env, existing_search_paths); EXPECT_TRUE(s.empty()); - existing_search_paths = { "d", "e" }; + existing_search_paths.insert(existing_search_paths.end(), { "d", "e" }); s = getAllSearchPaths(search_paths_env, existing_search_paths); EXPECT_EQ(s.size(), 2); } @@ -171,8 +174,8 @@ TEST(BoostPluginLoaderUnit, LoadTestPlugin) // NOLINT { PluginLoader plugin_loader; - plugin_loader.search_paths.insert(std::string(PLUGIN_DIR)); - plugin_loader.search_libraries.insert(std::string(PLUGINS_MULTIPLY)); + plugin_loader.search_paths.emplace_back(PLUGIN_DIR); + plugin_loader.search_libraries.emplace_back(PLUGINS_MULTIPLY); EXPECT_TRUE(plugin_loader.isPluginAvailable(getSymbolName())); auto plugin = plugin_loader.createInstance(getSymbolName()); @@ -198,7 +201,7 @@ TEST(BoostPluginLoaderUnit, LoadTestPlugin) // NOLINT { // Use full path PluginLoader plugin_loader; const std::string full_path = boost_plugin_loader::decorate(std::string(PLUGINS_MULTIPLY), std::string(PLUGIN_DIR)); - plugin_loader.search_libraries.insert(full_path); + plugin_loader.search_libraries.push_back(full_path); EXPECT_TRUE(plugin_loader.isPluginAvailable(getSymbolName())); auto plugin = plugin_loader.createInstance(getSymbolName()); @@ -227,7 +230,7 @@ TEST(BoostPluginLoaderUnit, LoadTestPlugin) // NOLINT PluginLoader plugin_loader; EXPECT_EQ(plugin_loader.count(), 0); EXPECT_TRUE(plugin_loader.empty()); - plugin_loader.search_libraries.insert(std::string(PLUGINS_MULTIPLY)); + plugin_loader.search_libraries.emplace_back(PLUGINS_MULTIPLY); EXPECT_EQ(plugin_loader.count(), 1); EXPECT_FALSE(plugin_loader.empty()); @@ -242,8 +245,8 @@ TEST(BoostPluginLoaderUnit, LoadTestPlugin) // NOLINT { PluginLoader plugin_loader; plugin_loader.search_system_folders = false; - plugin_loader.search_paths.insert("does_not_exist"); - plugin_loader.search_libraries.insert(std::string(PLUGINS_MULTIPLY)); + plugin_loader.search_paths.emplace_back("does_not_exist"); + plugin_loader.search_libraries.emplace_back(PLUGINS_MULTIPLY); EXPECT_FALSE(plugin_loader.isPluginAvailable(getSymbolName())); // Behavior change: used to return nullptr but now throws exception @@ -255,7 +258,7 @@ TEST(BoostPluginLoaderUnit, LoadTestPlugin) // NOLINT { PluginLoader plugin_loader; plugin_loader.search_system_folders = false; - plugin_loader.search_libraries.insert(std::string(PLUGINS_MULTIPLY)); + plugin_loader.search_libraries.emplace_back(PLUGINS_MULTIPLY); { EXPECT_FALSE(plugin_loader.isPluginAvailable("does_not_exist")); @@ -277,7 +280,7 @@ TEST(BoostPluginLoaderUnit, LoadTestPlugin) // NOLINT { PluginLoader plugin_loader; plugin_loader.search_system_folders = false; - plugin_loader.search_libraries.insert("does_not_exist"); + plugin_loader.search_libraries.emplace_back("does_not_exist"); { EXPECT_FALSE(plugin_loader.isPluginAvailable(getSymbolName())); @@ -299,7 +302,7 @@ TEST(BoostPluginLoaderUnit, LoadTestPlugin) // NOLINT { PluginLoader plugin_loader; plugin_loader.search_system_folders = false; - plugin_loader.search_libraries.insert(std::string(PLUGINS_MULTIPLY)); + plugin_loader.search_libraries.emplace_back(PLUGINS_MULTIPLY); // NOLINTNEXTLINE(cppcoreguidelines-avoid-goto) const std::vector plugins = plugin_loader.getAvailablePlugins(TestPluginMultiply::getSection()); @@ -309,7 +312,7 @@ TEST(BoostPluginLoaderUnit, LoadTestPlugin) // NOLINT { PluginLoader plugin_loader; plugin_loader.search_system_folders = true; - plugin_loader.search_libraries.insert(std::string(PLUGINS_MULTIPLY)); + plugin_loader.search_libraries.emplace_back(PLUGINS_MULTIPLY); const std::vector plugins = plugin_loader.getAvailablePlugins(TestPluginMultiply::getSection()); EXPECT_EQ(plugins.size(), 1); @@ -362,8 +365,8 @@ TEST(BoostPluginLoaderUnit, LoadTestPluginsSameSymbolDifferentSections) // NOLI // Try to load an instance of `TestPluginAddImpl` from the library in which `TestPluginMultiplyImpl` was defined { PluginLoader plugin_loader; - plugin_loader.search_libraries.insert(PLUGINS_MULTIPLY); - plugin_loader.search_paths.insert(PLUGIN_DIR); + plugin_loader.search_libraries.emplace_back(PLUGINS_MULTIPLY); + plugin_loader.search_paths.emplace_back(PLUGIN_DIR); // NOLINTNEXTLINE(cppcoreguidelines-avoid-goto) EXPECT_ANY_THROW(plugin_loader.createInstance(getSymbolName())); @@ -372,8 +375,8 @@ TEST(BoostPluginLoaderUnit, LoadTestPluginsSameSymbolDifferentSections) // NOLI // Try to load an instance of `TestPluginMultiplyImpl` from the library in which `TestPluginAddImpl` was defined { PluginLoader plugin_loader; - plugin_loader.search_libraries.insert(PLUGINS_ADD); - plugin_loader.search_paths.insert(PLUGIN_DIR); + plugin_loader.search_libraries.emplace_back(PLUGINS_ADD); + plugin_loader.search_paths.emplace_back(PLUGIN_DIR); // NOLINTNEXTLINE(cppcoreguidelines-avoid-goto) EXPECT_ANY_THROW(plugin_loader.createInstance(getSymbolName())); @@ -382,9 +385,9 @@ TEST(BoostPluginLoaderUnit, LoadTestPluginsSameSymbolDifferentSections) // NOLI // Given both libraries, correctly load and use each plugin, even though they share the same symbol name { PluginLoader plugin_loader; - plugin_loader.search_libraries.insert(PLUGINS_ADD); - plugin_loader.search_libraries.insert(PLUGINS_MULTIPLY); - plugin_loader.search_paths.insert(PLUGIN_DIR); + plugin_loader.search_libraries.emplace_back(PLUGINS_ADD); + plugin_loader.search_libraries.emplace_back(PLUGINS_MULTIPLY); + plugin_loader.search_paths.emplace_back(PLUGIN_DIR); // Load and use a multiply plugin {