diff --git a/container/src/root/common/utility.hh b/container/src/root/common/utility.hh index 01c5cf9..20c3daa 100644 --- a/container/src/root/common/utility.hh +++ b/container/src/root/common/utility.hh @@ -1,6 +1,6 @@ // docker-finance | modern accounting for the power-user // -// Copyright (C) 2021-2025 Aaron Fiore (Founder, Evergreen Crypto LLC) +// Copyright (C) 2021-2026 Aaron Fiore (Founder, Evergreen Crypto LLC) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -412,10 +412,10 @@ class PluggablePath bool m_is_repo, m_is_custom; }; -//! \brief Base namespace handler for various pluggables (plugins and macros) +//! \brief Base pluggable space handler for various pluggables (plugins and macros) //! -//! \details Handles pluggable namespace, typically used by pluggable -//! implementations when auto-(un|re)loading. +//! \details Handles pluggable namespace and entrypoint class name, +//! typically used by pluggable implementations when auto-(un|re)loading. //! //! \ingroup cpp_plugin_impl cpp_macro_impl //! \since docker-finance 1.1.0 @@ -437,8 +437,8 @@ class PluggableSpace !std::regex_match( parsed, std::regex{ - "[a-zA-Z0-9:/_\\-]+"} /* TODO(unassigned): refine */), - "invalid characters in namespace"); + "[a-zA-Z0-9:/_\\-\\.]+"} /* TODO(unassigned): refine */), + "invalid characters in pluggable space"); if (parsed.find('/')) { @@ -448,6 +448,10 @@ class PluggableSpace { parsed = std::regex_replace(parsed, std::regex{"-"}, "_"); } + if (parsed.find('.')) + { + parsed = std::regex_replace(parsed, std::regex{"\\."}, "_"); + } } return parsed; @@ -455,6 +459,7 @@ class PluggableSpace m_space.outer(parser(m_space.outer())); m_space.inner(parser(m_space.inner())); + m_space.entry(parser(m_space.entry())); return *this; } @@ -462,7 +467,7 @@ class PluggableSpace protected: // \note Since the current presumption is that a PluggableSpace is likely // to be derived from an operating system path (via PluggablePath), - // there's leeway for path-to-namespace conversions to be done here. + // there's leeway for path-to-space conversions to be done here. explicit PluggableSpace(const type::PluggableSpace& space) : m_space(space) { parse(); @@ -491,12 +496,18 @@ class PluggableSpace //! \return The pluggable's inner namespace const std::string& inner() const { return m_space.inner(); } + //! \return The pluggable's entrypoint class name + const std::string& entry() const { return m_space.entry(); } + //! \return true if the outer namespace was set bool has_outer() const { return !m_space.outer().empty(); } //! \return true if the inner namespace was set bool has_inner() const { return !m_space.inner().empty(); } + //! \return true if the entrypoint class name was set + bool has_entry() const { return !m_space.entry().empty(); } + private: type::PluggableSpace m_space; }; @@ -610,7 +621,8 @@ class Pluggable // Execute pluggable's loader const std::string s{ - "dfi::" + m_plug.space().outer() + "::" + m_plug.space().inner()}; + "dfi::" + m_plug.space().outer() + "::" + m_plug.space().inner() + + "::" + m_plug.space().entry()}; ::dfi::common::line(s + "::load(\"" + m_plug.args().load() + "\")"); return *this; @@ -624,7 +636,8 @@ class Pluggable { // Execute pluggable's unloader const std::string s{ - "dfi::" + m_plug.space().outer() + "::" + m_plug.space().inner()}; + "dfi::" + m_plug.space().outer() + "::" + m_plug.space().inner() + + "::" + m_plug.space().entry()}; ::dfi::common::line(s + "::unload(\"" + m_plug.args().unload() + "\")"); // Unload pluggable file