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