ALib C++ Framework
by
Library Version: 2605 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
recordparser.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//==================================================================================================
8
9/// This sub-namespace holds entities of the module \alib_enumrecords, which are accessed by
10/// including #"F;ALib.EnumRecords.Bootstrap.H".
12
13/// This is a pure static type used for parsing enum records from strings.
14/// The static fields are initialized with each method of type #"EnumRecords"
15/// and therefore implementations of #"EnumRecordPrototype::Parse;*" can rely on finding
16/// these fields properly set.
17///
18/// This concept makes use of the restriction that the setup of
19/// #"alib_enums_records;ALib Enum Records" must exclusively be done during
20/// #"alib_mod_bs;bootstrapping" of the process, where no multi-threading is active, yet.
21///
22/// If parse errors occur, a <c>std::runtime_error</c> is thrown.
23///
24/// The methods of this type perform strict checks about unnecessary whitespaces, <c>'+'</c>-signs,
25/// etc, which also raise an exception. The rationale for this design decision
26/// (to not allow unnecessary, but maybe unharmful characters in resources) besides saving memory is,
27/// that the occurrence of unnecessary characters, indicates an erroneous maintenance of
28/// externalized resources, and such should be detected as soon as possible.
29///
30/// The main interface into this class is given with the overloaded methods #".Get(String&)".
31/// Enum Records are usually rather simple structs, consisting of strings, characters, integers
32/// and floating point values. If so, a simple list of invocations of #"%Get(String&)" for each
33/// field of the struct has to be placed in implementations of the method
34/// \note
35/// This is the only occasion where any \alib module throws an exception of type \c std.
36/// If (in presence of the module \alib_exceptions) an #"exc Exception" was thrown,
37/// this had to be resourced likewise.
38/// The rationale for this design decision is that enum records usually are defined by
39/// potentially externalized resources. The maintenance of such resources must not lead to
40/// corrupted exceptions that are thrown when parsing those resources.
41/// Consequently, the exception messages are using the English language and are not externalized.
42/// An end user will not be faced with these exceptions unless an erroneous "roll-out"
43/// of software using malicious externalized resources was performed.
44///
45/// For the last field, the optional parameter \p{isLastField} has to be given as \c true.
46/// As an example, the following code shows the implementation of #"Declaration::Parse;*":
47/// \snippet "variables/vmeta.cpp" DOX_ENUMS_RECORD_PARSER
48/// This parse method omits reading the value for inherited field
49/// #"ERSerializable::MinimumRecognitionLength;*", and sets it to fixed \c 0 instead.
50/// This is often an option when custom enumeration record types
51/// are derived from #"%ERSerializable" but are not supposed to be deserialized, or deserialization
52/// forcing the whole string to read is acceptable.
53/// Note that it is still possible to deserialize elements, but not with abbreviated names.
54///
55/// An implementation for a custom record type might perform more complex parsing operations.
56/// For this, some helper methods are publicly provided, and finally, the direct use of the
57/// substring #"Input" is likewise allowed.
59 /// The remaining input string.
61
62 /// The delimiter of fields of a record.
64
65 /// The delimiter of records.
67
68 /// A backup of the originally given string to parse.
70
71 /// The resource category (if a resourced string was parsed).
73
74 /// The resource name (if a resourced string was parsed).
76
77 /// Initializes this parser. This is done once before reading a resource (or static) string
78 /// with enum record definitions.
79 ///
80 /// @param input The input string.
81 /// @param innerDelim The delimiter of fields of a record.
82 /// @param outerDelim The delimiter of records.
83 /// @param resourceCategory The delimiter of records.
84 /// @param resourceName The delimiter of records.
85 ALIB_DLL static void Initialize(const String& input ,
86 character innerDelim , character outerDelim,
87 const NString& resourceCategory, const NString& resourceName) {
88 // Test for double initialization call, what is not easily avoidable for resourced strings.
89 // This protects the resource information, of the first call.
90 if( input.Buffer() != Input.Buffer() || Input.IsNull() ) {
91 Input =
92 OriginalInput = input;
93 InnerDelimChar = innerDelim;
94 OuterDelimChar = outerDelim;
95 ResourceCategory = resourceCategory;
96 ResourceName = resourceName;
97 if( input.IsNull () ) error( "Input string is nulled" );
98 if( input.IsEmpty() ) error( "Input string is empty" );
99 } }
100
101 //################################################################################################
102 // Helpers
103 //################################################################################################
104
105 /// Throws a <c>std::runtime_error</c>.
106 /// @param what Textual description about what has been tried to do.
107 ALIB_DLL static void error[[noreturn]] (const NCString& what);
108
109 /// Asserts that no whitespaces follow in input.
110 /// Throws a <c>std::runtime_error</c> in case.
111 /// @param where Textual description about what is currently done.
112 ALIB_DLL static void assertNoWhitespaces(const NCString& where);
113
114 /// Asserts that no trailing whitespaces are in \p{token}.
115 /// Throws a <c>std::runtime_error</c> in case.
116 /// @param token The string to test for trailing whitespaces.
118
119
120 /// Asserts that a specific redundant character is not given, for example, a leading
121 /// <c>'+'</c> sign for an integral value.
122 /// Throws a <c>std::runtime_error</c> in case.
123 /// @param specificChar The character to check.
124 /// @param where Textual description about what is currently done.
125 ALIB_DLL static void assertNoUnnecessary(character specificChar, const NCString& where);
126
127 /// Asserts that either \p{specificChar} follows. The character will also be consumed.
128 /// @param specificChar The character to consume next.
129 /// @param where Textual description about what is currently done.
130 ALIB_DLL static void assertChar(character specificChar, const NCString& where);
131
132 /// Asserts that either #"Input" is empty, or an #"OuterDelimChar" follows.
133 /// Throws a <c>std::runtime_error</c> in case.
135
136 /// Asserts that the #".Input" is empty.
137 /// Throws a <c>std::runtime_error</c> in case.
139
140 /// Used by #".Get(TIntegral&, bool)".
141 /// Reads special values \b min, \b max and \b ^N. The latter provides the power of two.
142 /// @param isLastField Has to be given as \c true, if this is the last field to parse,
143 /// otherwise \c false.
144 /// @return The value parsed.
145 ALIB_DLL static integer getInteger( bool isLastField );
146
147
148 //################################################################################################
149 // Main methods for parsing fields.
150 //################################################################################################
151 /// Parses a field of string-type. Parsing ends with an #".InnerDelimChar".
152 /// The string is checked for not containing leading or trailing whitespaces.<br>
153 ///
154 /// @param result A reference to the record's field to be read.
155 /// @param isLastField Has to be given as \c true, if this is the last field to parse.
156 /// Defaults to \c false.
157 ALIB_DLL static void Get( String& result, bool isLastField= false );
158
159 /// Parses a field of character type.
160 ///
161 /// @param result A reference to the record's field to be read.
162 /// @param isLastField Has to be given as \c true, if this is the last field to parse.
163 /// Defaults to \c false.
164 ALIB_DLL static void Get( character& result, bool isLastField= false );
165
166 /// Parses an integral field of a record. Accepts <c>'-'</c> signs, while <c>'+'</c>
167 /// is considered an unnecessary token.
168 /// Furthermore asserts that at least one digit was parsed.
169 ///
170 /// Allows special values \b min, \b max and \b ^N. The latter provides the power of two.
171 ///
172 /// @tparam TIntegral The integer type to parse.
173 /// Must be statically castable from \b uint64_t.
174 /// Deduced by the compiler.
175 /// @param result A reference to the record's field to be read.
176 /// @param isLastField Has to be given as \c true, if this is the last field to parse.
177 /// Defaults to \c false.
178 template<typename TIntegral>
179 requires std::integral<TIntegral>
180 static void Get( TIntegral& result, bool isLastField= false ) {
181 integer bigInt= getInteger( isLastField );
182 if( bigInt == (std::numeric_limits<integer>::max)() ) result= (std::numeric_limits<TIntegral>::max)();
183 else if( bigInt == (std::numeric_limits<integer>::min)() ) result= (std::numeric_limits<TIntegral>::min)();
184 else result= static_cast<TIntegral>( bigInt );
185 }
186
187 /// Parses an enumeration element value, which has to be given in the source string by its
188 /// underlying integral value. (It is not possible to parse "named" enumerations in
189 /// bootstrapping, yet.)
190 ///
191 /// \note
192 /// This method uses #".Get(TIntegral&, bool)" to read the value and thus special values
193 /// \b min, \b max and \b ^N are allowed
194 ///
195 /// @tparam TEnum The enum type to parse an element from.
196 /// @param result A reference to the integer variable to parse.
197 /// @param isLastField Has to be given as \c true, if this is the last field to parse.
198 /// Defaults to \c false.
199 template<typename TEnum>
200 requires std::is_enum_v<TEnum>
201 static void Get( TEnum& result, bool isLastField= false ) {
202 typename std::underlying_type<TEnum>::type resultIntegral;
203 EnumRecordParser::Get( resultIntegral, isLastField );
204 result= TEnum( resultIntegral );
205 }
206
207 /// Parses the next floating point field of a record. Accepts <c>'-'</c> signs, while <c>'+'</c>
208 /// is considered an unnecessary token.
209 /// Furthermore asserts that at least one digit was parsed.
210 ///
211 /// @param result A reference to the record's field to be read.
212 /// @param isLastField Has to be given as \c true, if this is the last field to parse.
213 /// Defaults to \c false.
214 ALIB_DLL static void Get( double& result, bool isLastField= false );
215
216 /// Removes an #".InnerDelimChar".
217 /// The #".Input" is checked for not containing whitespaces before or after the delimiter.
218 ALIB_DLL static void Delim();
219
220 /// Removes an #".OuterDelimChar".
221 /// The #".Input" is checked for not containing whitespaces before or after the delimiter.
222 ALIB_DLL static void OuterDelim();
223};
224
225} // namespace [alib::enumrecords::bootstrap]
#define ALIB_DLL
#define ALIB_EXPORT
constexpr bool IsEmpty() const
Definition string.hpp:349
constexpr const TChar * Buffer() const
Definition string.hpp:295
constexpr bool IsNull() const
Definition string.hpp:334
strings::TString< nchar > NString
Type alias in namespace #"%alib".
Definition string.hpp:2174
strings::TCString< nchar > NCString
Type alias in namespace #"%alib".
Definition cstring.hpp:408
lang::integer integer
Type alias in namespace #"%alib".
Definition integers.hpp:149
strings::TString< character > String
Type alias in namespace #"%alib".
Definition string.hpp:2165
strings::TSubstring< character > Substring
Type alias in namespace #"%alib".
characters::character character
Type alias in namespace #"%alib".
static void Get(double &result, bool isLastField=false)
static NString ResourceCategory
The resource category (if a resourced string was parsed).
static void assertChar(character specificChar, const NCString &where)
static void error(const NCString &what)
static void Get(String &result, bool isLastField=false)
static void Get(character &result, bool isLastField=false)
static void Get(TEnum &result, bool isLastField=false)
static character OuterDelimChar
The delimiter of records.
static void Get(TIntegral &result, bool isLastField=false)
static Substring Input
The remaining input string.
static character InnerDelimChar
The delimiter of fields of a record.
static NString ResourceName
The resource name (if a resourced string was parsed).
static void assertNoTrailingWhitespaces(String &token)
static void Initialize(const String &input, character innerDelim, character outerDelim, const NString &resourceCategory, const NString &resourceName)
static void assertNoUnnecessary(character specificChar, const NCString &where)
static String OriginalInput
A backup of the originally given string to parse.
static void assertNoWhitespaces(const NCString &where)
static integer getInteger(bool isLastField)