ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
inmemoryplugin.hpp
Go to the documentation of this file.
1/** ************************************************************************************************
2 * \file
3 * This header file is part of module \alib_config of the \aliblong.
4 *
5 * \emoji :copyright: 2013-2024 A-Worx GmbH, Germany.
6 * Published under \ref mainpage_license "Boost Software License".
7 **************************************************************************************************/
8#ifndef HPP_ALIB_CONFIG_INMEMORY_PLUGIN
9#define HPP_ALIB_CONFIG_INMEMORY_PLUGIN 1
10
11#if !defined (HPP_ALIB_CONFIG_PLUGINS)
13#endif
14#if !defined(HPP_ALIB_MONOMEM_HASHMAP)
16#endif
17#if !defined(HPP_ALIB_MONOMEM_LIST)
18# include "alib/monomem/list.hpp"
19#endif
20
21namespace alib { namespace config {
22
23/** ************************************************************************************************
24 * Specialization of abstract interface class #ConfigurationPlugin, which holds
25 * configuration variables in memory. Instances of this class are used to create two plug-ins
26 * within standard configurations:
27 * - One with priority
28 * \alib{config;Priorities;Priorities::DefaultValues} (low priority)
29 * to store default values not found in other configuration plug-ins and
30 * - a second with priority
31 * \alib{config;Priorities;Priorities::ProtectedValues} (maximum priority),
32 * which can be used protect configuration values from external changes.
33 *
34 * This class in addition acts as the parent of class
35 * \ref alib::config::IniFile "IniFile" and may be used likewise as a base of custom plug-ins.
36 *
37 * To serve the \b IniFile requirements, this plug-ing divides the set of variables into sections
38 * (according to the category of a variable), allows comment strings for variables and sections,
39 * and virtualizes some key methods to allow descendants to take specific actions.
40 *
41 * ## Monotonic Allocation ##
42 * This type uses monotonic allocation for all internal data, except long name and comment strings.
43 * Nevertheless, due to the recycling facilities of the container types of module
44 * \alib_monomem, it is 100% safe against memory exhaustion, independent from the number
45 * of repeated insert and delete operations.
46 **************************************************************************************************/
48{
49 #if !defined(ALIB_DOX)
50 friend class InMemoryPluginIteratorImpl;
51 friend class Configuration;
52 #endif
53
54 // #############################################################################################
55 // Types
56 // #############################################################################################
57 public:
58 class Section;
59 class Entry;
60
61 protected:
62 /** The list type used by struct \b Section to store entries. */
64
65 /** The list type used by struct \b Entry to store additional values of multi-value
66 * entries. */
68
69 public:
70 /** ****************************************************************************************
71 * A section entry. Corresponds to a configuration \alib{config;Variable}.
72 ******************************************************************************************/
73 class Entry
74 {
75 #if !defined(ALIB_DOX)
76 friend class InMemoryPlugin;
77 #endif
78
79 protected:
80 /** The entry's name */
82
83 public:
84 /** The comments of the section. */
86
87 /** The delimiter (for splitting output into multiple lines). */
89
90 /** The format hints of the variable */
91 FormatHints FmtHints = FormatHints::None;
92
93 /** Used to vertically align attributes in multi-line attributes.
94 * Use cases are "=", ":" or "->".<br>
95 * Used by \alib{config;IniFile} and potentially by custom derived plug-in types. */
97
98 /** The first values of the entry. */
100
101 /** The rest of the values. */
103
104 /** The value as received from an external source. Derived types may use this
105 * "original" value in the case that it was not changed by software.
106 * For example in case of INI-files, this approach preserves a user's manual
107 * format, when writing back the file. */
109
110 /**
111 * Constructs an Entry
112 * @param pName The name of the entry.
113 * @param pAllocator The allocator used for the list of additional values.
114 * @param recycler The recycler for value entries.
115 */
116 Entry( const String& pName,
117 MonoAllocator* pAllocator,
118 TValueList::TSharedRecycler& recycler )
119 : AdditionalValues( pAllocator, recycler )
120 {
125
126 name.Reset(pName);
127 }
128
129 /**
130 * Returns the (unique) name of this entry.
131 * @return The name of this entry
132 */
133 const String& Name() const
134 {
135 return name;
136 }
137
138
139 /**
140 * Increases or shrinks the number of elements in #AdditionalValues to match
141 * the given \p{requestedSize} <b>- 1</b>.
142 * @param requestedSize The requested number of values of this entry.
143 * @return An iterator pointing to the first additional value, hence the second
144 * value of this entry.
145 */
146 TValueList::Iterator SetValueCount( integer requestedSize )
147 {
148 integer valSize= static_cast<integer>( AdditionalValues.Size() + 1 );
149 while (valSize < requestedSize )
150 {
151 AdditionalValues.EmplaceBack();
152 AdditionalValues.Back().DbgDisableBufferReplacementWarning();
153 ++valSize;
154 }
155 while (valSize > requestedSize )
156 {
157 AdditionalValues.PopBack();
158 --valSize;
159 }
160
161 return AdditionalValues.begin();
162 }
163 }; // class Entry
164
165
166
167 /** ****************************************************************************************
168 * A configuration section. Corresponds to a configuration category.
169 ******************************************************************************************/
171 {
172 #if !defined(ALIB_DOX)
173 friend class InMemoryPlugin;
174 friend class InMemoryPluginIteratorImpl;
175 friend class Configuration;
176 #endif
177
178 protected:
179 String32 name; ///< The name of the section.
180 TEntryList entries; ///< The list of variables of the section.
181
182 public:
183 mutable AString Comments; ///< The comments of the section. This object is
184 ///< mutable with constant instances.
185
186 /**
187 * Constructs a section.
188 * @param sectionName The name of the section.
189 * @param pAllocator The allocator used for the list of entries.
190 * @param recycler The recycler for the list of entries.
191 */
192 Section(const String& sectionName,
193 MonoAllocator* pAllocator,
194 TEntryList::TSharedRecycler& recycler )
195 : entries( pAllocator, recycler )
196 {
198 name.Reset(sectionName);
199 }
200
201 /**
202 * Returns the (unique) name of this section.
203 * @return The name of this entry.
204 */
205 const String& Name() const
206 {
207 return name;
208 }
209
210 /**
211 * Returns the (unique) name of this section.
212 * @return The name of this entry.
213 */
214 const TEntryList& Entries() const
215 {
216 return entries;
217 }
218
219 };
220
221 // #############################################################################################
222 // Hashtable for entries
223 // #############################################################################################
224 protected:
225 /** Hash functor for nodes hashed in field #entryTable. */
226 struct EntryKey
227 {
228 const String& SectionName; ///< The name of the section.
229 const String& EntryName; ///< The name of the entry.
230
231 /** Constructor.
232 * @param sectionName The section's name of an entry.
233 * @param entryName The name of an entry.
234 */
235 EntryKey( const String& sectionName, const String& entryName )
236 : SectionName( sectionName)
237 , EntryName ( entryName )
238 {}
239
240 /** Hash functor for nodes hashed in field \alib{config::InMemoryPlugin;entryTable}. */
241 struct Hash
242 {
243 /**
244 * Calculates a hash code for \b NodeKey objects.
245 * @param key The key to hash.
246 * @return The hash code.
247 */
248 std::size_t operator()(const EntryKey& key) const
249 {
252 }
253 };
254
255 /** Equality functor for nodes in field \alib{config::InMemoryPlugin;entryTable}. */
256 struct EqualTo
257 {
258 /**
259 * Invokes \alib{strings;TString::Equals;String::Equals} on \p{lhs}, passing \p{rhs}
260 * and returns the result.
261 * @param lhs The first string object.
262 * @param rhs The second string object.
263 * @return The result of the string comparison.
264 */
265 bool operator()(const EntryKey& lhs, const EntryKey& rhs ) const
266 {
267 return ( (lhs.SectionName.IsEmpty() && rhs.SectionName.IsEmpty() )
268 || lhs.SectionName.Equals<false, lang::Case::Ignore>( rhs.SectionName ) )
269 && ( (lhs.EntryName .IsEmpty() && rhs.EntryName .IsEmpty() )
270 || lhs.EntryName .Equals<false, lang::Case::Ignore>( rhs.EntryName ) );
271 }
272 };
273
274 };
275
276 // #############################################################################################
277 // protected fields
278 // #############################################################################################
279 protected:
280 /** A monotonic allocator used for allocating sections and entries. */
282
283 /** The name of the plug-in. Provided in constructor, returned with #Name. */
285
286 /** The shared recycler for \b Entry list nodes.
287 * This object is passed to the entry list of each section. */
288 TEntryList::TSharedRecycler entryRecycler;
289
290 /** The shared recycler for value list nodes of struct \b Entry.
291 * This object is passed to the value list of each entry. */
292 TValueList::TSharedRecycler valueRecycler;
293
294 /**
295 * The entry hash set.
296 * This is used to find entries by section name and entry name.
297 * The set contains all entries of all sections.
298 */
302
303
304 /** The list of sections. */
306
307 /**
308 * If a monotonic allocator instance was provided from outside, this flag is \c false.
309 * otherwise \c true.
310 */
312
313 // #############################################################################################
314 // Constructor/destructor
315 // #############################################################################################
316 public:
317 /** ****************************************************************************************
318 * Constructor.
319 * @param pName The name of the plug-in as returned with #Name.
320 * @param externalMA External monotonic allocator. If not given, an internal one
321 * is created.
322 * Optional and defaults to \c nullptr.
323 ******************************************************************************************/
325 InMemoryPlugin( String pName, MonoAllocator* externalMA= nullptr );
326
327 /** ****************************************************************************************
328 * Virtual Destructor.
329 ******************************************************************************************/
331 virtual
332 ~InMemoryPlugin() override;
333
334 // #############################################################################################
335 // Conversion of variables to entries and vice versa.
336 // #############################################################################################
337 /**
338 * Virtual method that copies the values of an entry to the given \p{variable}.
339 *
340 * @param entry The entry to convert.
341 * @param variable The variable to fill with our values.
342 */
344 virtual void ToVariable( Entry& entry, Variable& variable ) const;
345
346 /**
347 * Virtual method that copies the values of the given \p{variable} to an entry.
348 *
349 * @param entry The entry to convert.
350 * @param variable The variable to fill with our values.
351 */
353 virtual void FromVariable( Entry& entry, Variable& variable ) const;
354
355 // #############################################################################################
356 // Interface
357 // #############################################################################################
360
361 /** ****************************************************************************************
362 * Clears all configuration data.
363 ******************************************************************************************/
365 virtual void Clear();
366
367 /** ****************************************************************************************
368 * Searches the \ref alib::config::InMemoryPlugin::Section "Section" with the given
369 * name.
370 *
371 * @param sectionName The name of the section to be retrieved.
372 * @return Returns the section if it was found, nullptr otherwise.
373 ******************************************************************************************/
375 const Section* SearchSection( const String& sectionName );
376
377 /** ****************************************************************************************
378 * Searches the \ref alib::config::InMemoryPlugin::Section "Section" with the given
379 * name. If the section was not found, it is created.
380 *
381 * @param sectionName The name of the section to be retrieved.
382 * @return Returns a <c>std::pair</c> with the first element being a pointer to the section
383 * and the second a boolean that is \c true if the section was created and \c false
384 * otherwise.
385 ******************************************************************************************/
387 std::pair<Section*, bool>
388 SearchOrCreateSection( const String& sectionName );
389
390 /** ****************************************************************************************
391 * Searches an entry with the given name.
392 * @param section The name of the section.
393 * @param name The name of the entry to be searched.
394 * @return The entry if found, else \c nullptr.
395 ******************************************************************************************/
396 Entry* SearchEntry ( const String& section, const String& name )
397 {
398 return &*searchEntry( section, name );
399 }
400
401 /** ****************************************************************************************
402 * Searches an entry with the given name.
403 * @param section The section.
404 * @param name The name of the entry to be searched.
405 * @return The entry if found, else \c nullptr.
406 ******************************************************************************************/
407 Entry* SearchEntry ( Section* section, const String& name )
408 {
409 return &*searchEntry( section->name, name );
410 }
411
412 /** ****************************************************************************************
413 * Returns a constant reference to the sections of this plug-in.
414 * @return The list of sections.
415 ******************************************************************************************/
416 const List<Section>& Sections() const
417 {
418 return sections;
419 }
420
421 // #############################################################################################
422 // ConfigurationPlugin interface implementation
423 // #############################################################################################
424 public:
425
426 /** ****************************************************************************************
427 * Abstract method to return a plug-in name. The name may be used in human readable
428 * output, e.g. log-files or exception messages to tell a user for example, which plug-in
429 * loaded a variable containing a syntax error.
430 * @return The name of the plug-in.
431 ******************************************************************************************/
432 virtual String Name() const override
433 {
434 return plugInName;
435 }
436
437 /** ****************************************************************************************
438 * Searches the variable in our storage.
439 *
440 * @param variable The variable to retrieve.
441 * @param searchOnly If \c true, the variable is not read. Defaults to \c false.
442 * @return \c true if variable was found, \c false if not.
443 ******************************************************************************************/
445 virtual bool Load( Variable& variable, bool searchOnly= false ) override;
446
447 /** ****************************************************************************************
448 * Creates or replaces existing variable in our storage.
449 * If the variable has no value, an existing entry is deleted.
450 *
451 * @param variable The variable to retrieve.
452 * @return \c true if the variable was written, \c false if not. The latter might only
453 * happen if the variable given was illegal, e.g. empty name.
454 ******************************************************************************************/
456 virtual bool Store( Variable& variable ) override;
457
458 /** ****************************************************************************************
459 * Creates an iterator object to return all variables within a section.
460 *
461 * The iterator object returned, needs to be deleted by the caller.
462 *
463 * \note Method \alib{config;Configuration::GetIterator} returns an iterator that allows
464 * to iterate across all variables of a section found in all plug-ins
465 *
466 * @param sectionName The name of the section to iterate.
467 *
468 * @returns The iterator requested.
469 ******************************************************************************************/
471 virtual Iterator* GetIterator( const String& sectionName ) override;
472
473 // #############################################################################################
474 // Internals
475 // #############################################################################################
476 protected:
477 /** ****************************************************************************************
478 * Appends a new section to the end of the list.
479 * Must be invoked only if the section does not exist, yet.
480 * @param sectionName The name of the section.
481 * @return The entry if found, else \c nullptr.
482 ******************************************************************************************/
483 virtual Section* createSection( const String& sectionName )
484 {
485 return &sections.EmplaceBack( sectionName, allocator, entryRecycler );
486 }
487
488 /** ****************************************************************************************
489 * Searches an entry with the given name. The search is performed case insensitive.
490 * @param section The name of the section
491 * @param name The name of the entry to be searched.
492 * @return The entry if found, else \c nullptr.
493 ******************************************************************************************/
494 Entry* searchEntry (const String& section, const String& name )
495 {
496 auto it= entryTable.Find( EntryKey(section, name ) );
497 if( it != entryTable.end() )
498 return &*it.Mapped().second;
499 return nullptr;
500 }
501
502 /** ****************************************************************************************
503 * Creates a new entry.
504 * Must be invoked only if the entry does not exist, yet.
505 * @param section The section.
506 * @param name The name of the entry to be created.
507 * @return The entry found or created.
508 ******************************************************************************************/
510 Entry* createEntry ( Section* section, const String& name )
511 {
512 auto entryIt= section->entries.Emplace ( section->entries.end(),
513 name, allocator, valueRecycler );
514 entryTable .EmplaceUnique( EntryKey(section->Name(), entryIt->Name()),
515 std::make_pair(section, entryIt) );
516 return &*entryIt;
517 }
518
519}; // InMemoryPlugin
520
521
522} // namespace alib[::onfig]
523
524/// Type alias in namespace \b alib.
526
527} // namespace [alib]
528
529#endif // HPP_ALIB_CONFIG_INMEMORY_PLUGIN
virtual bool Store(Variable &variable)
virtual ALIB_API bool Load(Variable &variable, bool searchOnly=false)=0
TValueList::Iterator SetValueCount(integer requestedSize)
Entry(const String &pName, MonoAllocator *pAllocator, TValueList::TSharedRecycler &recycler)
TEntryList entries
The list of variables of the section.
String32 name
The name of the section.
Section(const String &sectionName, MonoAllocator *pAllocator, TEntryList::TSharedRecycler &recycler)
List< Entry, Recycling::Shared > TEntryList
Entry * SearchEntry(const String &section, const String &name)
List< String32, Recycling::Shared > TValueList
const List< Section > & Sections() const
virtual ALIB_API void ToVariable(Entry &entry, Variable &variable) const
ALIB_API Entry * createEntry(Section *section, const String &name)
ALIB_API std::pair< Section *, bool > SearchOrCreateSection(const String &sectionName)
virtual ALIB_API bool Load(Variable &variable, bool searchOnly=false) override
virtual ALIB_API Iterator * GetIterator(const String &sectionName) override
virtual Section * createSection(const String &sectionName)
monomem::HashMap< EntryKey, std::pair< Section *, TEntryList::Iterator >, EntryKey::Hash, EntryKey::EqualTo > entryTable
virtual ALIB_API void Clear()
Entry * SearchEntry(Section *section, const String &name)
virtual String Name() const override
virtual ALIB_API void FromVariable(Entry &entry, Variable &variable) const
virtual ALIB_API bool Store(Variable &variable) override
ALIB_API const Section * SearchSection(const String &sectionName)
TEntryList::TSharedRecycler entryRecycler
virtual ALIB_API ~InMemoryPlugin() override
TValueList::TSharedRecycler valueRecycler
Entry * searchEntry(const String &section, const String &name)
void DbgDisableBufferReplacementWarning()
Definition astring.hpp:353
constexpr bool IsEmpty() const
Definition string.hpp:414
std::size_t HashcodeIgnoreCase() const
bool Equals(const TString< TChar > &rhs) const
Definition string.hpp:573
#define ALIB_API
Definition alib.hpp:538
Definition alib.cpp:57
characters::character character
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:286
config::InMemoryPlugin InMemoryPlugin
Type alias in namespace alib.
bool operator()(const EntryKey &lhs, const EntryKey &rhs) const
std::size_t operator()(const EntryKey &key) const
const String & EntryName
The name of the entry.
const String & SectionName
The name of the section.
EntryKey(const String &sectionName, const String &entryName)