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