ALib C++ Framework
by
Library Version: 2605 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
records.hpp
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of the module \alib_enumrecords of the \aliblong.
4///
5/// Copyright 2013-2026 A-Worx GmbH, Germany.
6/// Published under #"mainpage_license".
7//==================================================================================================
8ALIB_EXPORT namespace alib { namespace enumrecords {
9
10//##################################################################################################
11// RecordsTraits
12//##################################################################################################
13
14//==================================================================================================
15/// This type trait is used to associate an <b><em>"ALib Enum Record"</em></b> type to a
16/// (scoped or non-scoped) enumeration type.
17///
18/// In the non-specialized version type definition #".Type" (the only entity of this struct)
19/// evaluates to <c>void</c>. To assign a record, specify a data record type, similar to what
20/// is prototyped with #"EnumRecordPrototype"
21///
22/// \see
23/// Please consult chapter #"alib_enums_records" of the Programmer's Manual
24/// of \alib_enumrecords_nl for detailed documentation and sample code on this struct and
25/// underlying concept.
26///
27/// \see
28/// Macro #"ALIB_ENUMS_ASSIGN_RECORD" offers a well readable alternative to specialize this
29/// struct for an enum type.
30///
31/// @tparam TEnum The enumeration type this struct applies to.
32//==================================================================================================
33template<typename TEnum>
34requires std::is_enum<TEnum>::value
36 /// The data type associated with elements of \p{TEnum}.
37 using Type= void;
38};
39
40
42
43/// Concept that is satisfied if the type trait #"RecordsTraits" is specialized for the template
44/// type \p{TEnum} which specifies type alias #"%RecordsTraits::Type;2".
45/// @tparam TEnum The type to test.
46template<typename TEnum>
47concept HasRecords = !std::same_as<void, typename RecordsTraits<TEnum>::Type>;
48
50
51
52//##################################################################################################
53// detail {}
54//##################################################################################################
55/// Details of namespace #"alib::enumrecords;2".
56namespace detail {
57
58//##################################################################################################
59// Detail functions
60//##################################################################################################
61//==================================================================================================
62/// Stores the \p{record} for enum \p{element} of the given enum type \p{rtti}.
63/// If a value already exists, it is ignored. This allows having multiple records, while only
64/// the first is found.
65/// @param rtti The enumeration type.
66/// @param integral The integral value of the enum element.
67/// @param record The record to associate.
68//==================================================================================================
70void setEnumRecord( const std::type_info& rtti, integer integral, const void* record );
71
72//==================================================================================================
73/// Retrieves the enum record stored for the enum element with integral value \p{integral} of
74/// enum type \p{rtti}.
75/// @param rtti The enumeration type.
76/// @param integral The integral value of the enum element.
77/// @return A pointer to the record, \c nullptr if not found.
78//==================================================================================================
80const void* getEnumRecord( const std::type_info& rtti, integer integral );
81
82
83//==================================================================================================
84/// This is the internal singleton that provides a link to the first
85/// #"alib_enums_records;ALib Enum Record".
86/// The class inherit's #"Singleton" and has a private default constructor, what
87/// makes this type a #"alib_singleton_strict;strict singleton".
88///
89/// Because enum record types are ensured to be trivially destructible types, no destructor is given.
90///
91/// @tparam TEnum The enumeration type associated with enum records.
92//==================================================================================================
93template<typename TEnum>
94struct EnumRecordHook : Singleton<EnumRecordHook<TEnum>> {
95 #if !DOXYGEN
97 #endif
98
99 /// The enum's underlying integer type.
100 using TIntegral= typename std::underlying_type<TEnum>::type;
101
102 /// The enum's associated record type.
104
105
106 /// A node of the forward list that contains the custom record data
107 struct Node {
108 /// The enum element's underlying integral value.
110
111 /// The data record.
113
114 /// Pointer to the next node.
116
117 /// Constructs this instance taking variadic template arguments to construct the contained
118 /// enum record of custom type.
119 ///
120 /// @tparam TArgs Types of the variadic arguments \p{args}.
121 /// @param element The enum element
122 /// @param args Variadic arguments forwarded to constructor of field #".record".
123 template <typename... TArgs>
124 Node( TEnum element, TArgs&&... args) noexcept
125 : integral( TIntegral(element) )
126 , record ( std::forward<TArgs>(args)... ) {}
127
128 /// Default constructor.
129 Node() noexcept =default;
130
131 };
132
133 /// The hook to the first record defined.
135
136 /// Helper methods that returns the address of field
137 /// #"EnumRecordHook::Node::next" the last element contained in the
138 /// list. If no elements have been initialized, yet, the address of field #".first" is
139 /// returned.
140 /// @return A pointer to the pointer of the last element or this hook.
142 auto** last= &first;
143 while( (*last) != nullptr )
144 last= &(*last)->next;
145 return last;
146 }
147
148 private:
149 /// Private default constructor, what makes this type a
150 /// #"alib_singleton_strict;strict singleton".
151 ///
152 /// \note As enum record types are trivially destructible types, no destructor is given.
154 : first( nullptr ) {}
155}; // EnumRecordHook
156} //namespace alib::enumrecords[::detail]
157
158//##################################################################################################
159// GetRecord/TryRecord
160//##################################################################################################
162
163/// Returns the enum record for element \p{element} of enumeration type \p{TEnum} .
164/// In debug-compilations an \alib_assertion is raised if no enum record was defined for
165/// \p{element}.
166///
167/// Internally, references to enum records are stored in a hash map. With that, this method executes
168/// in constant time <em>O(1)</em> in the average case.
169///
170/// \see
171/// - Function #"enumrecords::TryRecord;*" which returns a pointer to the record and \c nullptr if
172/// no record was defined for \p{element}.
173/// - Class #"%Enum" of the module \alib_boxing and according namespace functions
174/// #"boxing::GetRecord;*" and #"boxing::TryRecord;*", which together allow collecting the
175/// necessary runtime information to defer the retrieval of enum records.
176///
177/// @tparam TEnum The enumeration type. Deduced from given argument.
178/// @param element The enum element to search for.
179/// @return The record that is associated with \p{element}.
180template<typename TEnum>
182const RecordsTraits<TEnum>::Type& GetRecord( TEnum element ) {
183 static_assert( std::is_trivially_destructible<typename RecordsTraits<TEnum>::Type>::value,
184 "Error: Enum Record types must be a trivially destructible." );
185
186 const void* result= detail::getEnumRecord( typeid(TEnum), integer(element) );
187 ALIB_ASSERT_ERROR( result != nullptr, "ENUMS", "Enum Record for type <{}>({}) not found.",
188 &typeid(TEnum), UnderlyingIntegral(element) )
189 return *static_cast<const RecordsTraits<TEnum>::Type*>( result );
190}
191
192//==================================================================================================
193/// If defined, returns a pointer to the enum record for element \p{element} of enumeration
194/// type \p{TEnum} .
195/// If no enum record was defined, \c nullptr is returned.
196///
197/// \see
198/// - Function #"enumrecords::GetRecord" which returns a reference and asserts in debug-compilations
199/// if no record is defined for \p{element} during bootstrap.
200/// - Class #"%Enum" of the module \alib_boxing and the corresponding functions
201/// #"boxing::GetRecord;*" and #"boxing::TryRecord;*", which together allow the collection
202/// of the necessary runtime information and defer the retrieval of enum records.
203///
204/// @tparam TEnum The enumeration type. Deduced from given argument.
205/// @param element The enum element to search for.
206/// @return A pointer to the record that is associated with \p{element}, respectively \c nullptr
207/// if no record was defined.
208//==================================================================================================
209template<typename TEnum>
211const typename RecordsTraits<TEnum>::Type* TryRecord( TEnum element ) {
212 static_assert( std::is_trivially_destructible<typename RecordsTraits<TEnum>::Type>::value,
213 "Error: Enum Record types must be a trivially destructible." );
214
215 return static_cast<const RecordsTraits<TEnum>::Type*>(
216 detail::getEnumRecord( typeid(TEnum), integer(element) ) );
217}
218
219#include "ALib.Lang.CIMethods.H"
220
221//##################################################################################################
222// struct EnumRecords
223//##################################################################################################
224//==================================================================================================
225/// This is a pure static interface type usable with enumeration types that dispose of a
226/// specialization of the type trait #"RecordsTraits".
227///
228/// The type has two main purposes:
229///
230/// 1. Providing overloaded methods #"Bootstrap" which allow to defined enum data records during
231/// #"alib_mod_bs;bootstrapping of ALib" and the using software.
232/// 2. Providing an iterator over all records defined for elements of \p{TEnum}.
233///
234/// A third purpose, namely to retrieve the default (single) enumeration record for a specific enum
235/// element is not provided by this type, but instead offered with likewise templated namespace
236/// functions
237/// - #"enum GetRecord" and
238/// - #"enum TryRecord".
239///
240/// \note
241/// The rationale for this is techical: Using namespace methods, the compiler can deduce
242/// template parameter \p{TEnum} from the function parameter, which was not possible if the
243/// functions were static methods of this templated type.
244///
245/// \attention
246/// While this type becomes available with the inclusion if the header #"F;ALib.EnumRecords.H",
247/// the overloaded #"%Bootstrap" methods (which are to be used solely during bootstrap, with
248/// single-threaded access to this backend), become available only with further inclusion of
249/// #"F;ALib.EnumRecords.Bootstrap.H".
250///
251/// The rationale for the above is twofold: It reduces header-file dependencies from the majority
252/// of code that just use enum records and not defne them. Secondly, it stresses the fact that
253/// the variouos #"%Bootstrap" methods must be used only while bootstrapping is done.
254///
255/// \see Chapter #"alib_enums_records;ALib Enum Records" of the Programmer's Manual of this
256/// module.
257///
258/// @tparam TEnum The enumeration type that the static methods of this type are to use.
259//==================================================================================================
260template<typename TEnum>
263 static_assert( std::is_trivially_destructible<typename RecordsTraits<TEnum>::Type>::value,
264 "Error: Enum Record types must be a trivially destructible." );
265
266 /// Defaulted constructor.
267 EnumRecords() noexcept =default;
268
269 /// The enum's underlying integer type.
270 using TIntegral= typename std::underlying_type<TEnum>::type;
271
272 /// The enum's associated record type.
273 using TRecord = typename RecordsTraits<TEnum>::Type;
274
275 /// Tests if \p{TEnum} has an associated record type that either is or is derived from
276 /// type \p{TRecord}.
277 /// @tparam TRecord The enum record base type required.
278 /// @tparam TAssociated Deduced by the compiler. Must not be specified.
279 /// @return Returns \c true if the given record type is the same or a base class of the
280 /// record type associated with the given enum. Otherwise, returns \c false.
281 template<typename TRecord, typename TAssociated= typename RecordsTraits<TEnum>::Type>
282 static constexpr bool AreOfType() { return std::is_base_of_v<TRecord, TAssociated>; }
283
284 /// Implementation of \c std::iterator_traits for enum records.
285 /// Begin- and end-iterators can be received with \e static methods
286 /// #"EnumRecords::begin;*" and #"EnumRecords::end;*". In ranged base
287 /// <c>for(:)</c> loops, a local instance of type #"%EnumRecords" has to be created.
288 ///
289 /// As the name of the class indicates, this iterator satisfies the C++ standard library
290 /// concept \https{ForwardIterator,en.cppreference.com/w/cpp/concept/ForwardIterator}.
292 private:
293 #if !DOXYGEN
294 friend struct EnumRecords;
295 #endif
296
297
298 /// Shortcut to the record hook's inner node type (linked list).
300
301 /// The current node this iterator refers to.
303
304 /// Constructor.
305 /// @param start Pointer to the initial element.
306 ForwardIterator( Node* start ) noexcept
307 : node( start ) {}
308
309 using iterator_category = std::forward_iterator_tag; ///< Implementation of <c>std::iterator_traits</c>.
310 using value_type = const TRecord& ; ///< Implementation of <c>std::iterator_traits</c>.
311 using difference_type = integer ; ///< Implementation of <c>std::iterator_traits</c>.
312 using pointer = const TRecord* ; ///< Implementation of <c>std::iterator_traits</c>.
313 using reference = const TRecord& ; ///< Implementation of <c>std::iterator_traits</c>.
314
315 public:
316
317 //########################## To satisfy concept of InputIterator ########################
318
319 /// Prefix increment operator.
320 /// @return A reference to this object.
321 ForwardIterator& operator++() { node= node->next; return *this; }
322
323 /// Postfix increment operator.
324 /// @return An iterator value that is not increased, yet.
326
327 /// Comparison operator.
328 /// @param other The iterator to compare ourselves to.
329 /// @return \c true if this and the given iterator are pointing to the same element,
330 /// \c false otherwise.
331 bool operator==(ForwardIterator other) const { return node == other.node; }
332
333 /// Comparison operator.
334 /// @param other The iterator to compare ourselves to.
335 /// @return \c true if this and given iterator are not equal, \c false otherwise.
336 bool operator!=(ForwardIterator other) const { return !(*this == other); }
337
338 //##################################### Member access ####################################
339
340 /// Returns the enum element of the enum record that this iterator refers to.
341 /// @return The enum element the current record is associated to.
342 TEnum Enum() const { return TEnum( node->integral ); }
343
344 /// Returns the underlying integral value of the enum element of the enum record
345 /// that this iterator refers to.
346 /// @return The integral value of the enum element the current record is associated
347 /// to.
348 TIntegral Integral() const { return node->integral; }
349
350 /// Returns a constant reference to the enum record this iterator refers to.
351 /// @return The current enum record.
352 const TRecord& operator*() const { return node->record; }
353
354 /// Returns a constant pointer to the enum record this iterator refers to.
355 /// @return The current enum record.
356 const TRecord* operator->() const { return &node->record; }
357 }; // inner struct ForwardIterator
358
359 /// Returns an iterator referring to the first enum record defined for type \p{TEnum}.
360 ///
361 /// \note
362 /// Receiving the list of enum records is internally implemented using class
363 /// #"Singleton" and executes in constant time <em>O(1)</em>, in effect almost
364 /// no time.
365 ///
366 /// \note
367 /// Like any other entity in this class, this method is static, apart from a defaulted
368 /// (empty) constructor, which is provided for the sole purpose of allowing
369 /// range-based <em><c>for(:)</c></em> loops.
370 ///
371 /// @return An iterator to the first record defined for enumeration type \p{TEnum}.
372 static
375
376 /// Returns an iterator referring to the first element behind the list.
377 ///
378 /// \see The note documented with the sibling method #".begin".
379 /// @return The end of the list.
380 static constexpr
381 ForwardIterator end() { return ForwardIterator( nullptr ); }
382}; // struct EnumRecords
383
384//##################################################################################################
385// ERSerializable
386//##################################################################################################
387
388//==================================================================================================
389/// This is a <em>built-in</em> record type that can be used to equip custom enumeration types
390/// with #"alib_enums_records;ALib Enum Records".
391///
392/// This record has two members, #".EnumElementName" and #".MinimumRecognitionLength" which usually
393/// determines an element's name in a human-readable format, respectively how many starting
394/// characters are to be read to recognize the element when parsed.
395///
396/// Basic versions of such serialization and de-serialization is implemented with this module
397/// and documented with chapter
398/// #"alib_enums_records_details_serialization" of the
399/// Programmer's Manual of this \alibmod_nl. This functionality is likewise available for
400/// enumerations equipped with a custom record type that derives from this type. For this reason,
401/// all built-in record types of various \alibmods_nl derive from this type.
402///
403/// If deserialization is not of importance, a derived type may choose to not parse member
404/// #".MinimumRecognitionLength" from a (resourced) string, but initialize it to fixed \c 0 value.
405/// This behavior is, for example, implemented with record #"ERException" and various
406/// types found in module \alib_app.
407///
408/// \see For more information, see:
409/// - Concept #"IsSerializable".
410/// - Chapter #"alib_enums_records;ALib Enum Records" and its subsection
411/// #"alib_enums_records_details_serialization".
412/// - Specializations
413/// #"APPENDABLES::AppendableTraits<TEnum,TChar,TAllocator>" and
414/// #"APPENDABLES::AppendableTraits<TBitwiseEnum,TChar,TAllocator>",
415/// which allows write enumeration element names to instances of class #"^AString".
416/// - Namespace functions of this module for parsing enum element values:
417/// - #"enumrecords::Parse"
418/// - #"ParseBitwise" and
419/// - #"ParseEnumOrTypeBool".
420//==================================================================================================
422 /// The name of the enum element.
424
425 /// Built-in basic de-serialization functions #"enumrecords::Parse", #"ParseBitwise" and
426 /// #"ParseEnumOrTypeBool" interpret this value as the minimum length (abbreviation)
427 /// to accept when an enum element name is parsed.
428 /// If \c 0 or negative, the complete #".EnumElementName" is expected.
430
431
432 /// Defaulted constructor leaving the record undefined.
433 ERSerializable() noexcept =default;
434
435 /// Constructor. This is either called by descendants or by user code that omits the preferred
436 /// option of parsing resourced strings for the creation of enum records.
437 ///
438 /// Note that parameter \p{name} has to be of "static nature", which means the buffer and
439 /// contents of the string is deemed to survive the life-cycle of an application.
440 /// With direct invocation, usually, C++ string literals are passed.
441 ///
442 /// @param name The name of this element.
443 /// @param minLength The minimum length to recognise an element when de-serialized.
444 /// (Assigned to field #".MinimumRecognitionLength".)
445 ERSerializable( const String& name, int minLength= 0 ) noexcept
446 : EnumElementName (name)
447 , MinimumRecognitionLength(minLength) {}
448
449 /// Parses the fields of this record from the #"%^Substring" \p{parser} given as reference.
450 /// In case of an error, an \alib_exception is raised because parsing has to succeed.
451 ///
452 /// @see
453 /// This is the implementation of a method needed with template programming, as described in
454 /// #"EnumRecordPrototype::Parse;*".
456 void Parse();
457};
458
460
461/// Concept that is satisfied if the type trait #"RecordsTraits"
462/// is specialized for type \p{TEnum} and its type-alias member #"RecordsTraits::Type" evaluates to
463/// #"ERSerializable" or a derived type thereof.
464/// @tparam TEnum The type to test.
465template<typename TEnum>
466concept IsSerializable = std::is_base_of_v<ERSerializable, typename RecordsTraits<TEnum>::Type>;
467
469
470
471} // namespace alib[::enumrecords]
472
473/// Type alias in namespace #"%alib".
474template<typename TEnum>
476
477} // namespace [alib]
#define ALIB_DLL
#define ALIB_ALLOW_DOCS
#define ALIB_POP_ALLOWANCE
#define ALIB_EXPORT
#define ALIB_ASSERT_ERROR(cond, domain,...)
Details of namespace #"alib::enumrecords;2".
void setEnumRecord(const std::type_info &rtti, integer elementValue, const void *record)
Definition records.cpp:25
const void * getEnumRecord(const std::type_info &rtti, integer elementValue)
Definition records.cpp:33
const RecordsTraits< TEnum >::Type & GetRecord(TEnum element)
Definition records.hpp:182
bool Parse(strings::TSubstring< TChar > &input, TEnum &result)
const RecordsTraits< TEnum >::Type * TryRecord(TEnum element)
Definition records.hpp:211
Definition alox.cpp:14
singletons::Singleton< T > Singleton
Type alias in namespace #"%alib".
lang::integer integer
Type alias in namespace #"%alib".
Definition integers.hpp:149
enumrecords::EnumRecords< TEnum > EnumRecords
Type alias in namespace #"%alib".
Definition records.hpp:475
strings::TString< character > String
Type alias in namespace #"%alib".
Definition string.hpp:2165
String EnumElementName
The name of the enum element.
Definition records.hpp:423
ERSerializable() noexcept=default
Defaulted constructor leaving the record undefined.
bool operator==(ForwardIterator other) const
Definition records.hpp:331
Node * node
The current node this iterator refers to.
Definition records.hpp:302
bool operator!=(ForwardIterator other) const
Definition records.hpp:336
const TRecord * pointer
Implementation of std::iterator_traits.
Definition records.hpp:312
typename detail::EnumRecordHook< TEnum >::Node Node
Shortcut to the record hook's inner node type (linked list).
Definition records.hpp:299
integer difference_type
Implementation of std::iterator_traits.
Definition records.hpp:311
const TRecord & reference
Implementation of std::iterator_traits.
Definition records.hpp:313
std::forward_iterator_tag iterator_category
Implementation of std::iterator_traits.
Definition records.hpp:309
const TRecord & value_type
Implementation of std::iterator_traits.
Definition records.hpp:310
EnumRecords() noexcept=default
Defaulted constructor.
typename std::underlying_type< TEnum >::type TIntegral
The enum's underlying integer type.
Definition records.hpp:270
static constexpr bool AreOfType()
Definition records.hpp:282
typename RecordsTraits< TEnum >::Type TRecord
The enum's associated record type.
Definition records.hpp:273
static ForwardIterator begin()
Definition records.hpp:373
static constexpr ForwardIterator end()
Definition records.hpp:381
void Type
The data type associated with elements of TEnum.
Definition records.hpp:37
A node of the forward list that contains the custom record data.
Definition records.hpp:107
Node * next
Pointer to the next node.
Definition records.hpp:115
TIntegral integral
The enum element's underlying integral value.
Definition records.hpp:109
Node() noexcept=default
Default constructor.
Node(TEnum element, TArgs &&... args) noexcept
Definition records.hpp:124
typename std::underlying_type< TEnum >::type TIntegral
The enum's underlying integer type.
Definition records.hpp:100
Node * first
The hook to the first record defined.
Definition records.hpp:134
typename RecordsTraits< TEnum >::Type TRecord
The enum's associated record type.
Definition records.hpp:103