ALib C++ Library
Library Version: 2511 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 /// Default constructor.
132 Node() noexcept =default;
133
134 };
135
136 /// The hook to the first record defined.
138
139 /// Helper methods that returns the address of field
140 /// \alib{enumrecords::detail;EnumRecordHook::Node::next} the last element contained in the
141 /// list. If no elements have been initialized, yet, the address of field #first is
142 /// returned.
143 /// @return A pointer to the pointer of the last element or this hook.
145 auto** last= &first;
146 while( (*last) != nullptr )
147 last= &(*last)->next;
148 return last;
149 }
150
151 private:
152 /// Private default constructor, what makes this type a
153 /// \ref alib_singleton_strict "strict singleton".
154 ///
155 /// \note As enum record types are trivially destructible types, no destructor is given.
157 : first( nullptr ) {}
158}; // EnumRecordHook
159} //namespace alib::enumrecords[::detail]
160
161//##################################################################################################
162// GetRecord/TryRecord
163//##################################################################################################
165
166/// Returns the enum record for element \p{element} of enumeration type \p{TEnum} .
167/// In debug-compilations an \alib_assertion is raised if no enum record was defined for
168/// \p{element}.
169///
170/// Internally, references to enum records are stored in a hash map. With that, this method executes
171/// in constant time <em>O(1)</em> in the average case.
172///
173/// \see
174/// - Function \alib{enumrecords;TryRecord} which returns a pointer to the record and \c nullptr if
175/// no record was defined for \p{element}.
176/// - Class \b Enum of the module \alib_boxing and according namespace functions
177/// \alib{boxing;GetRecord} and \alib{boxing;TryRecord}, which together allow collecting the
178/// necessaryrun-time information to defer the retrieval of enum records.
179///
180/// @tparam TEnum The enumeration type. Deduced from given argument.
181/// @param element The enum element to search for.
182/// @return The record that is associated with \p{element}.
183template<typename TEnum>
185const RecordsTraits<TEnum>::Type& GetRecord( TEnum element ) {
186 static_assert( std::is_trivially_destructible<typename RecordsTraits<TEnum>::Type>::value,
187 "Error: Enum Record types must be a trivially destructible." );
188
189 const void* result= detail::getEnumRecord( typeid(TEnum), integer(element) );
190 ALIB_ASSERT_ERROR( result != nullptr, "ENUMS", "Enum Record for type <{}>({}) not found.",
191 &typeid(TEnum), UnderlyingIntegral(element) )
192 return *reinterpret_cast<const RecordsTraits<TEnum>::Type*>( result );
193}
194
195//==================================================================================================
196/// If defined, returns a pointer to the enum record for element \p{element} of enumeration
197/// type \p{TEnum} .
198/// If no enum record was defined, \c nullptr is returned.
199///
200/// \see
201/// - Function \alib{enumrecords;GetRecord} which returns a reference and asserts in debug-compilations
202/// if no record is defined for \p{element} during bootstrap.
203/// - Class \b Enum of the module \alib_boxing and the corresponding functions
204/// \alib{boxing;GetRecord} and \alib{boxing;TryRecord}, which together allow the collection
205/// of the necessary run-time information and defer the retrieval of enum records.
206///
207/// @tparam TEnum The enumeration type. Deduced from given argument.
208/// @param element The enum element to search for.
209/// @return A pointer to the record that is associated with \p{element}, respectively \c nullptr
210/// if no record was defined.
211//==================================================================================================
212template<typename TEnum>
214const typename RecordsTraits<TEnum>::Type* TryRecord( TEnum element ) {
215 static_assert( std::is_trivially_destructible<typename RecordsTraits<TEnum>::Type>::value,
216 "Error: Enum Record types must be a trivially destructible." );
217
218 return reinterpret_cast<const typename RecordsTraits<TEnum>::Type*>(
219 detail::getEnumRecord( typeid(TEnum), integer(element) ) );
220}
221
222#include "ALib.Lang.CIMethods.H"
223
224//##################################################################################################
225// struct EnumRecords
226//##################################################################################################
227//==================================================================================================
228/// This is a pure static interface type usable with enumeration types that dispose of a
229/// specialization of the type trait \alib{enumrecords;RecordsTraits}.
230///
231/// The type has two main purposes:
232///
233/// 1. Providing overloaded methods #Bootstrap which allow to defined enum data records during
234/// \ref alib_mod_bs "bootstrapping of ALib" and the using software.
235/// 2. Providing an iterator over all records defined for elements of \p{TEnum}.
236///
237/// A third purpose, namely to retrieve the default (single) enumeration record for a specific enum
238/// element is not provided by this type, but instead offered with likewise templated namespace
239/// functions
240/// - \alib{enumrecords::GetRecord} and
241/// - \alib{enumrecords::TryRecord}.
242///
243/// \note
244/// The rationale for this is techical: Using namespace methods, the compiler can deduce
245/// template parameter \p{TEnum} from the function parameter, which was not possible if the
246/// functions were static methods of this templated type.
247///
248/// \attention
249/// While this type becomes available with the inclusion if the header \implude{EnumRecords},
250/// the overloaded \b Bootstrap methods (which are to be used solely during bootstrap, with
251/// single-threaded access to this backend), become available only with further inclusion of
252/// \implude{EnumRecords.Bootstrap}.
253///
254/// The rationale for the above is twofold: It reduces header-file dependencies from the majority
255/// of code that just use enum records and not defne them. Secondly, it stresses the fact that
256/// the variouos \b %Bootstrap methods must be used only while bootstrapping is done.
257///
258/// \see Chapter \ref alib_enums_records "ALib Enum Records" of the Programmer's Manual of this
259/// module.
260///
261/// @tparam TEnum The enumeration type that the static methods of this type are to use.
262//==================================================================================================
263template<typename TEnum>
266{
267 static_assert( std::is_trivially_destructible<typename RecordsTraits<TEnum>::Type>::value,
268 "Error: Enum Record types must be a trivially destructible." );
269
270 /// Defaulted constructor.
271 EnumRecords() noexcept =default;
272
273 /// The enum's underlying integer type.
274 using TIntegral= typename std::underlying_type<TEnum>::type;
275
276 /// The enum's associated record type.
277 using TRecord = typename RecordsTraits<TEnum>::Type;
278
279 /// Tests if \p{TEnum} has an associated record type that either is or is derived from
280 /// type \p{TRecord}.
281 /// @tparam TRecord The enum record base type required.
282 /// @tparam TAssociated Deduced by the compiler. Must not be specified.
283 /// @return Returns \c true if the given record type is the same or a base class of the
284 /// record type associated with the given enum. Otherwise, returns \c false.
285 template<typename TRecord, typename TAssociated= typename RecordsTraits<TEnum>::Type>
286 static constexpr bool AreOfType() { return std::is_base_of_v<TRecord, TAssociated>; }
287
288 /// Implementation of \c std::iterator_traits for enum records.
289 /// Begin- and end-iterators can be received with \e static methods
290 /// \alib{enumrecords;EnumRecords::begin} and \alib{enumrecords;EnumRecords::end}. In ranged base
291 /// <c>for(:)</c> loops, a local instance of type \b EnumRecords has to be created.
292 ///
293 /// As the name of the class indicates, this iterator satisfies the C++ standard library
294 /// concept \https{ForwardIterator,en.cppreference.com/w/cpp/concept/ForwardIterator}.
296 {
297 private:
298 #if !DOXYGEN
299 friend struct EnumRecords;
300 #endif
301
302
303 /// Shortcut to the record hook's inner node type (linked list).
305
306 /// The current node this iterator refers to.
308
309 /// Constructor.
310 /// @param start Pointer to the initial element.
311 ForwardIterator( Node* start ) noexcept
312 : node( start ) {}
313
314 using iterator_category = std::forward_iterator_tag; ///< Implementation of <c>std::iterator_traits</c>.
315 using value_type = const TRecord& ; ///< Implementation of <c>std::iterator_traits</c>.
316 using difference_type = integer ; ///< Implementation of <c>std::iterator_traits</c>.
317 using pointer = const TRecord* ; ///< Implementation of <c>std::iterator_traits</c>.
318 using reference = const TRecord& ; ///< Implementation of <c>std::iterator_traits</c>.
319
320 public:
321
322 //########################## To satisfy concept of InputIterator ########################
323
324 /// Prefix increment operator.
325 /// @return A reference to this object.
326 ForwardIterator& operator++() { node= node->next; return *this; }
327
328 /// Postfix increment operator.
329 /// @return An iterator value that is not increased, yet.
331
332 /// Comparison operator.
333 /// @param other The iterator to compare ourselves to.
334 /// @return \c true if this and the given iterator are pointing to the same element,
335 /// \c false otherwise.
336 bool operator==(ForwardIterator other) const { return node == other.node; }
337
338 /// Comparison operator.
339 /// @param other The iterator to compare ourselves to.
340 /// @return \c true if this and given iterator are not equal, \c false otherwise.
341 bool operator!=(ForwardIterator other) const { return !(*this == other); }
342
343 //##################################### Member access ####################################
344
345 /// Returns the enum element of the enum record that this iterator refers to.
346 /// @return The enum element the current record is associated to.
347 TEnum Enum() const { return TEnum( node->integral ); }
348
349 /// Returns the underlying integral value of the enum element of the enum record
350 /// that this iterator refers to.
351 /// @return The integral value of the enum element the current record is associated
352 /// to.
353 TIntegral Integral() const { return node->integral; }
354
355 /// Returns a constant reference to the enum record this iterator refers to.
356 /// @return The current enum record.
357 const TRecord& operator*() const { return node->record; }
358
359 /// Returns a constant pointer to the enum record this iterator refers to.
360 /// @return The current enum record.
361 const TRecord* operator->() const { return &node->record; }
362 }; // inner struct ForwardIterator
363
364 /// Returns an iterator referring to the first enum record defined for type \p{TEnum}.
365 ///
366 /// \note
367 /// Receiving the list of enum records is internally implemented using class
368 /// \alib{singletons;Singleton} and executes in constant time <em>O(1)</em>, in effect almost
369 /// no time.
370 ///
371 /// \note
372 /// Like any other entity in this class, this method is static, apart from a defaulted
373 /// (empty) constructor, which is provided for the sole purpose of allowing
374 /// range-based <em><c>for(:)</c></em> loops.
375 ///
376 /// @return An iterator to the first record defined for enumeration type \p{TEnum}.
377 static
380
381 /// Returns an iterator referring to the first element behind the list.
382 ///
383 /// \see The note documented with sibling method #begin.
384 /// @return The end of the list.
385 static constexpr
386 ForwardIterator end() { return ForwardIterator( nullptr ); }
387}; // struct EnumRecords
388
389//##################################################################################################
390// ERSerializable
391//##################################################################################################
392
393//==================================================================================================
394/// This is a <em>built-in</em> record type that can be used to equip custom enumeration types
395/// with \ref alib_enums_records "ALib Enum Records".
396///
397/// This record has two members, #EnumElementName and #MinimumRecognitionLength which usually
398/// determines an element's name in a human-readable format, respectively how many starting
399/// characters are to be read to recognize the element when parsed.
400///
401/// Basic versions of such serialization and de-serialization is implemented with this module
402/// and documented with chapter
403/// \ref alib_enums_records_details_serialization "4.3.1 Serialization/Deserialization" of the
404/// Programmer's Manual of this \alibmod_nl. This functionality is likewise available for
405/// enumerations equipped with a custom record type that derives from this type. For this reason,
406/// all built-in record types of various \alibmods_nl derive from this type.
407///
408/// If deserialization is not of importance, a derived type may choose to not parse member
409/// #MinimumRecognitionLength from a (resourced) string, but initialize it to fixed \c 0 value.
410/// This behavior is, for example, implemented with record \alib{exceptions;ERException} and various
411/// types found in module \alib_cli.
412///
413/// \see For more information, see:
414/// - Concept \alib{enumrecords;IsSerializable}.
415/// - Chapter \ref alib_enums_records "ALib Enum Records" and its subsection
416/// \ref alib_enums_records_details_serialization "4.3.1 Serialization/Deserialization".
417/// - Specializations
418/// \alib{strings::APPENDABLES;AppendableTraits<TEnum,TChar,TAllocator>} and
419/// \alib{strings::APPENDABLES;AppendableTraits<TBitwiseEnum,TChar,TAllocator>}.
420/// which allows write enumeration element names to instances of class
421/// \alib{strings;TAString;AString}.
422/// - Namespace functions of this module for parsing enum element values:
423/// - \alib{enumrecords;Parse}
424/// - \alib{enumrecords;ParseBitwise} and
425/// - \alib{enumrecords;ParseEnumOrTypeBool}.
426//==================================================================================================
428{
429 /// The name of the enum element.
431
432 /// Built-in basic de-serialization functions \alib{enumrecords;Parse}, \alib{enumrecords;ParseBitwise} and
433 /// \alib{enumrecords;ParseEnumOrTypeBool} interpret this value as the minimum length (abbreviation)
434 /// to accept when an enum element name is parsed.
435 /// If \c 0 or negative, the complete #EnumElementName is expected.
437
438
439 /// Defaulted constructor leaving the record undefined.
440 ERSerializable() noexcept =default;
441
442 /// Constructor. This is either called by descendants or by user code that omits the preferred
443 /// option of parsing resourced strings for the creation of enum records.
444 ///
445 /// Note that parameter \p{name} has to be of "static nature", which means the buffer and
446 /// contents of the string is deemed to survive the life-cycle of an application.
447 /// With direct invocation, usually, C++ string literals are passed.
448 ///
449 /// @param name The name of this element.
450 /// @param minLength The minimum length to recognise an element when de-serialized.
451 /// (Assigned to field #MinimumRecognitionLength.)
452 ERSerializable( const String& name, int minLength= 0 ) noexcept
453 : EnumElementName (name)
454 , MinimumRecognitionLength(minLength) {}
455
456 /// Parses the fields of this record from the \b Substring \p{parser} given as reference.
457 /// In case of an error, an \alib_exception is raised because parsing has to succeed.
458 ///
459 /// @see
460 /// This is the implementation of a method needed with template programming, as described in
461 /// \alib{enumrecords;EnumRecordPrototype::Parse}.
463 void Parse();
464};
465
467
468/// Concept that is satisfied if the type trait \alib{enumrecords;RecordsTraits}
469/// is specialized for type \p{TEnum} and its type-alias member \b Type evaluates to
470/// \alib{enumrecords;ERSerializable} or a derived type thereof.
471/// @tparam TEnum The type to test.
472template<typename TEnum>
473concept IsSerializable = std::is_base_of_v<ERSerializable, typename RecordsTraits<TEnum>::Type>;
474
476
477
478} // namespace alib[::enumrecords]
479
480/// Type alias in namespace \b alib.
481template<typename TEnum>
483
484} // namespace [alib]
#define ALIB_DLL
Definition alib.inl:503
#define ALIB_WARNINGS_RESTORE
Definition alib.inl:719
#define ALIB_WARNINGS_IGNORE_DOCS
Definition alib.inl:702
#define ALIB_EXPORT
Definition alib.inl:497
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1066
Details of namespace alib::enumrecords.
const void * getEnumRecord(const std::type_info &rtti, integer elementValue)
Definition records.cpp:70
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:185
const RecordsTraits< TEnum >::Type * TryRecord(TEnum element)
Definition records.inl:214
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:482
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2189
String EnumElementName
The name of the enum element.
Definition records.inl:430
ERSerializable() noexcept=default
Defaulted constructor leaving the record undefined.
bool operator==(ForwardIterator other) const
Definition records.inl:336
Node * node
The current node this iterator refers to.
Definition records.inl:307
bool operator!=(ForwardIterator other) const
Definition records.inl:341
const TRecord * pointer
Implementation of std::iterator_traits.
Definition records.inl:317
typename detail::EnumRecordHook< TEnum >::Node Node
Shortcut to the record hook's inner node type (linked list).
Definition records.inl:304
integer difference_type
Implementation of std::iterator_traits.
Definition records.inl:316
const TRecord & reference
Implementation of std::iterator_traits.
Definition records.inl:318
std::forward_iterator_tag iterator_category
Implementation of std::iterator_traits.
Definition records.inl:314
const TRecord & value_type
Implementation of std::iterator_traits.
Definition records.inl:315
EnumRecords() noexcept=default
Defaulted constructor.
static constexpr bool AreOfType()
Definition records.inl:286
static ForwardIterator begin()
Definition records.inl:378
static constexpr ForwardIterator end()
Definition records.inl:386
typename RecordsTraits< TEnum >::Type TRecord
The enum's associated record type.
Definition records.inl:277
typename std::underlying_type< TEnum >::type TIntegral
The enum's underlying integer type.
Definition records.inl:274
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:137
typename RecordsTraits< TEnum >::Type TRecord
The enum's associated record type.
Definition records.inl:105