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