ALib C++ Library
Library Version: 2312 R0
Documentation generated by doxygen
lib/fs_plugins/plugins.hpp
Go to the documentation of this file.
1 /** ************************************************************************************************
2  * \file
3  * This header file is part of file set \alibfs_plugins of the \aliblong.
4  *
5  * \emoji :copyright: 2013-2023 A-Worx GmbH, Germany.
6  * Published under \ref mainpage_license "Boost Software License".
7  **************************************************************************************************/
8 #ifndef HPP_ALIB_FS_PLUGINS_PLUGINS
9 #define HPP_ALIB_FS_PLUGINS_PLUGINS 1
10 
11 #if !defined(HPP_ALIB_MODULES) && !defined(ALIB_DOX)
12 # include "alib/lib/modules.hpp"
13 #endif
14 
15 ALIB_ASSERT_FILESET(PLUGINS)
16 
17 #if !defined(HPP_ALIB_TOOLS) && !defined(ALIB_DOX)
18 # include "alib/lib/tools.hpp"
19 #endif
20 
21 #if !defined(HPP_ALIB_FEATURES) && !defined(ALIB_DOX)
22 # include "alib/lib/features.hpp"
23 #endif
24 
25 #if !defined(HPP_ALIB_FS_COMMONENUMS_DEFS)
27 #endif
28 
29 #if !defined (HPP_ALIB_ENUMS_BITWISE)
30  #include "alib/enums/bitwise.hpp"
31 #endif
32 
33 #if !defined (_GLIBCXX_VECTOR) && !defined(_VECTOR_)
34 # include <vector>
35 #endif
36 
37 #if !defined (_GLIBCXX_ALGORITHM) && !defined(_ALGORITHM_)
38 # include <algorithm>
39 #endif
40 
41 namespace aworx { namespace lib { namespace detail {
42 
43 /** ************************************************************************************************
44  * This class usually is used as a base class for types that need to manage simple plug-ins.
45  * Within \alib itself, for example classes \alib{config,Configuration} and
46  * \alib{expressions,Compiler} inherit from this class.
47  *
48  * Plug-ins are organized with a prioritization. This means, that plug-ins which are inserted with
49  * a higher priority are 'asked' first, and those with a lower value become 'asked' only if higher
50  * prioritized plug-ins did not answer.<br>
51  * However, a derived class can deviate from this behavior. Using the typical \alib class design,
52  * all internal fields are \c protected, hence freely accessible by derived classes.
53  *
54  * @tparam pTPlugin The type of the plug-ins managed. This type is publicly exposed as #TPlugin.
55  * @tparam pTPriorities The enumeration type providing the default "plug-in slots" and priorities
56  * of the plug-ins managed. This type is publicly exposed as #TPriorities.
57  **************************************************************************************************/
58 template<typename pTPlugin, typename pTPriorities>
60 {
61  // #############################################################################################
62  // public fields and types
63  // #############################################################################################
64  public:
65 
66  /** This exposes the template parameter \p{pTPlugin} to the outer world. */
67  using TPlugin= pTPlugin;
68 
69  /** This exposes the template parameter \p{pTPlugin} to the outer world. */
70  using TPriorities= pTPriorities;
71 
72  /** Type definition for elements of the list of plug-ins with their priority. */
73  struct Slot
74  {
75  TPriorities priority; ///< The priority of the plug-in.
76  TPlugin* plugin; ///< The plug-in.
77  bool owned; ///< If \c true, this container is responsible for deleting
78  ///< the plug-in object.
79  };
80 
81  // #############################################################################################
82  // internal fields
83  // #############################################################################################
84  protected:
85 
86  /** The plug-ins we have attached in descending priority order. */
87  std::vector<Slot> plugins;
88 
89  // #############################################################################################
90  // Constructor/destructor
91  // #############################################################################################
92  public:
93  /** ****************************************************************************************
94  * Destructor. All plug-ins that were inserted with parameter \p{responsibility} set to
95  * \alib{Responsibility::Transfer} will be deleted.
96  ******************************************************************************************/
98  {
99  for( auto& slot : plugins )
100  if( slot.owned )
101  delete slot.plugin;
102  }
103 
104 
105 
106  // #############################################################################################
107  // interface
108  // #############################################################################################
109  public:
110  /** ****************************************************************************************
111  * Adds the given plug-in to the list of plug-ins..
112  * Higher numbers for parameter priority, prioritize this plug-in against those with
113  * lower values.
114  *
115  * Default values may be provided in case template type #TPriorities is an
116  * \alib{enums,T_EnumIsArithmetical,arithmetical enumeration}.
117  *
118  * @param plugin The plug-in to insert.
119  * @param priority The priority of the plug-in.
120  * @param responsibility If \c Responsibility::Transfer, the given plugin will be deleted
121  * with destruction of this object.
122  * Defaults to \c Responsibility::KeepWithSender which denotes that
123  * the life-cycle of the given external buffer is managed elsewhere.
124  ******************************************************************************************/
125  void InsertPlugin( TPlugin* plugin, TPriorities priority,
126  Responsibility responsibility
128  {
129  ALIB_ASSERT_ERROR( plugin != nullptr, "FSPLUGINS", "Nullptr provided for plugin." )
130 
131  static_assert( std::has_virtual_destructor<TPlugin>::value
132  || responsibility == Responsibility::KeepWithSender,
133  "Can't take responsibility for plug-in destruction. TPlugin has no virtual destructor." );
134 
135  plugins.insert( std::find_if( plugins.begin(), plugins.end(),
136  [priority]( Slot& ppp)
137  {
138  ALIB_ASSERT_ERROR( ppp.priority != priority, "FSPLUGINS",
139  "PluginContainer::InsertPlugin(): Plug-in with same priority exists" )
140 
141  return ppp.priority < priority;
142  } ),
143 
144  Slot {priority, plugin, responsibility == Responsibility::Transfer}
145  );
146 
147  }
148 
149 
150 
151  /** ****************************************************************************************
152  * Remove the given plug-in from the list of plug-ins.
153  *
154  * Responsibility for deletion of removed plug-ins is passed to the remover in case the
155  * plug-in was inserted with parameter \p{responsibility} set to
156  * \alib{Responsibility::Transfer}.
157  *
158  * @param plugIn The plug-in to be removed.
159  * @return \c true if the plug-in was removed, else \c false, which indicates that the
160  * given plug-in was not found.
161  ******************************************************************************************/
162  bool RemovePlugin( TPlugin* plugIn )
163  {
164  auto it= std::find_if( plugins.begin(), plugins.end(), [plugIn](Slot& pair)
165  {
166  return pair.plugin == plugIn;
167  } );
168  if( it != plugins.end() )
169  {
170  plugins.erase( it );
171  return true;
172  }
173 
174  ALIB_WARNING( "PluginContainer::RemovePlugin(): Plug-in not found for removal." )
175  return false;
176  }
177 
178  /** ****************************************************************************************
179  * Remove the plug-in at the given \p{idx} from the list of plug-ins.
180  *
181  * Responsibility for deletion of removed plug-ins is passed to the remover in case the
182  * plug-in was inserted with parameter \p{responsibility} set to
183  * \alib{Responsibility::Transfer}.
184  *
185  * @param idx The index of the plug-in to remove.
186  ******************************************************************************************/
187  void RemovePlugin( integer idx )
188  {
190  "FSPLUGINS: PluginContainer::RemovePlugin(): Index out of bounds: ", idx )
191  plugins.erase( plugins.begin() + idx );
192  }
193 
194 
195  /** ****************************************************************************************
196  * Remove the plug-in with the given priority.
197  *
198  * Responsibility for deletion of removed plug-ins is passed to the remover in case the
199  * plug-in was inserted with parameter \p{responsibility} set to
200  * \alib{Responsibility::Transfer}.
201  *
202  * @param priority The priority of the plug-in to remove.
203  * @return \c true if the plug-in was removed, else \c false, which indicates that no
204  * plug-in with the given priority was found.
205  ******************************************************************************************/
207  {
208  TPlugin* plugin= nullptr;
209  plugins.erase( std::remove_if( plugins.begin(), plugins.end(),
210  [priority, &plugin](Slot& entry)
211  {
212  if( entry.priority == priority)
213  {
214  plugin= entry.plugin;
215  return true;
216  }
217  return false;
218  } ),
219  plugins.end() );
220 
221  ALIB_ASSERT_WARNING( plugin, "FSPLUGINS",
222  "PluginContainer::RemovePlugin(): No Plug-in was removed " )
223 
224  return plugin;
225  }
226 
227 
228  /** ****************************************************************************************
229  * Checks if any plug-in is attached. This is useful if optional configuration objects
230  * are used. In case no plug-in was attached (by a third party), the effort to declare and
231  * search a variable can be omitted.
232  * @return \c true if this object has any plugin set, \c false otherwise.
233  ******************************************************************************************/
234  bool HasPlugins()
235  {
236  return CountPlugins() > 0;
237  }
238 
239  /** ****************************************************************************************
240  * Returns the number of plug-ins attached.
241  * @return The quantity of attached plug-ins.
242  ******************************************************************************************/
244  {
245  return static_cast<integer>(plugins.size());
246  }
247 
248  /** ****************************************************************************************
249  * Returns the plug-in with the given internal number. Valid numbers are
250  * 0..[#CountPlugins]. No internal checks for valid plug-in numbers are made.
251  *
252  * @param number The number of the plug-in requested.
253  * @return The plug-in requested or \c nullptr if not available.
254  ******************************************************************************************/
256  {
257  return plugins[static_cast<size_t>(number)].plugin;
258  }
259 
260 
261  /** ****************************************************************************************
262  * Returns the plug-in with the given priority. If the plug-in does not exist, \c nullptr
263  * is returned.
264  *
265  * @param priority The priority of the plug-in to return.
266  * @return The plug-in requested or \c nullptr if not available.
267  ******************************************************************************************/
269  {
270  auto it = std::find_if( plugins.begin(), plugins.end(),
271  [priority](Slot& pair) { return pair.priority == priority; } );
272  if( it != plugins.end() )
273  return it->plugin;
274  return nullptr;
275  }
276 
277  /** ****************************************************************************************
278  * Same as #GetPlugin, but converts the plug-in found to the template type, which has
279  * to be explicitly provided with the invocation of this method.
280  *
281  * A type-check is performed using standard C++ \c dynamic_cast mechanics.
282  * If the plugin has a different type, \c nullptr is returned.
283  *
284  * @tparam TPluginType The type of the plugin to search.
285  * @param priority The priority of the plug-in to return.
286  * @return The plug-in of requested type and priority. \c nullptr if not available.
287  ******************************************************************************************/
288  template<typename TPluginType>
289  TPluginType* GetPluginTypeSafe( TPriorities priority )
290  {
291  return dynamic_cast<TPluginType*>( GetPlugin( priority ) );
292  }
293 
294  /** ****************************************************************************************
295  * Searches the list of plug-ins for the first found with type \p{TPluginType}.
296  *
297  * @tparam TPluginType The type of the plugin to search.
298  * @return The plug-in of requested type. \c nullptr if not available.
299  ******************************************************************************************/
300  template<typename TPluginType>
301  TPluginType* GetPluginTypeSafe()
302  {
303  TPluginType* casted= nullptr;
304  for( auto& ppp : plugins )
305  if( (casted= dynamic_cast<TPluginType*>( ppp.plugin )) != nullptr )
306  break;
307 
308  return casted;
309  }
310 
311 }; // class PluginContainer
312 
313 }}} // namespace [aworx::lib::detail]
314 
315 
316 
317 
318 #endif // HPP_ALIB_FS_PLUGINS_PLUGINS
tools.hpp
aworx::lib::detail::PluginContainer::Slot
Definition: lib/fs_plugins/plugins.hpp:73
aworx::lib::integer
platform_specific integer
Definition: integers.hpp:49
features.hpp
ALIB_WARNING
#define ALIB_WARNING(...)
Definition: tools.hpp:182
aworx::lib::Responsibility
Responsibility
Definition: commonenumdefs.hpp:170
aworx::lib::detail::PluginContainer
Definition: lib/fs_plugins/plugins.hpp:59
aworx::lib::detail::PluginContainer::Slot::priority
TPriorities priority
The priority of the plug-in.
Definition: lib/fs_plugins/plugins.hpp:75
aworx::lib::Responsibility::KeepWithSender
Keeps responsibility, e.g. when passing an object.
ALIB_ASSERT_FILESET
#define ALIB_ASSERT_FILESET(filesetname)
Definition: modules.hpp:242
aworx::lib::detail::PluginContainer::plugins
std::vector< Slot > plugins
Definition: lib/fs_plugins/plugins.hpp:87
aworx::lib::config::Priorities
Priorities
Definition: priorities.hpp:37
aworx::lib::detail::PluginContainer::Slot::owned
bool owned
Definition: lib/fs_plugins/plugins.hpp:77
bitwise.hpp
modules.hpp
aworx::lib::detail::PluginContainer::GetPlugin
TPlugin * GetPlugin(integer number)
Definition: lib/fs_plugins/plugins.hpp:255
aworx::lib::detail::PluginContainer::CountPlugins
integer CountPlugins()
Definition: lib/fs_plugins/plugins.hpp:243
aworx::lib::detail::PluginContainer::RemovePlugin
void RemovePlugin(integer idx)
Definition: lib/fs_plugins/plugins.hpp:187
aworx::lib::detail::PluginContainer::TPriorities
pTPriorities TPriorities
Definition: lib/fs_plugins/plugins.hpp:70
aworx::lib::detail::PluginContainer::RemovePlugin
bool RemovePlugin(TPlugin *plugIn)
Definition: lib/fs_plugins/plugins.hpp:162
aworx::lib::detail::PluginContainer::~PluginContainer
~PluginContainer()
Definition: lib/fs_plugins/plugins.hpp:97
aworx
Definition: alox/alox.hpp:40
aworx::lib::detail::PluginContainer::GetPluginTypeSafe
TPluginType * GetPluginTypeSafe(TPriorities priority)
Definition: lib/fs_plugins/plugins.hpp:289
aworx::lib::detail::PluginContainer::RemovePlugin
TPlugin * RemovePlugin(TPriorities priority)
Definition: lib/fs_plugins/plugins.hpp:206
aworx::lib::detail::PluginContainer< ConfigurationPlugin, Priorities >::TPlugin
ConfigurationPlugin TPlugin
Definition: lib/fs_plugins/plugins.hpp:67
aworx::lib::detail::PluginContainer::InsertPlugin
void InsertPlugin(TPlugin *plugin, TPriorities priority, Responsibility responsibility=Responsibility::KeepWithSender)
Definition: lib/fs_plugins/plugins.hpp:125
ALIB_ASSERT_ERROR
#define ALIB_ASSERT_ERROR(cond,...)
Definition: tools.hpp:185
commonenumdefs.hpp
ALIB_ASSERT_WARNING
#define ALIB_ASSERT_WARNING(cond,...)
Definition: tools.hpp:186
aworx::lib::detail::PluginContainer::HasPlugins
bool HasPlugins()
Definition: lib/fs_plugins/plugins.hpp:234
aworx::lib::detail::PluginContainer::GetPluginTypeSafe
TPluginType * GetPluginTypeSafe()
Definition: lib/fs_plugins/plugins.hpp:301
aworx::lib::detail::PluginContainer::GetPlugin
TPlugin * GetPlugin(TPriorities priority)
Definition: lib/fs_plugins/plugins.hpp:268
aworx::lib::detail::PluginContainer::Slot::plugin
TPlugin * plugin
The plug-in.
Definition: lib/fs_plugins/plugins.hpp:76
aworx::lib::Responsibility::Transfer
Transfers responsibility to the receiving party.