ALib C++ Library
Library Version: 2510 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
declaration.inl
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_variables 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 variables {
9
10class Configuration;
11class Variable;
12
13namespace detail { class Entry; }
14
15//==================================================================================================
16/// \par Introduction
17/// This data record is used as an alternative (and often preferred) method to declare and optionally
18/// already define an \alib{variables;Variable;ALib Variable}.
19/// The record contains the following information:
20/// - The variables' name,
21/// - the variables' type name,
22/// - an optional defaultValue, and
23/// - optional comments.
24///
25/// The latter may be used by an external configuration file to place human-readable comments next
26/// to each configuration entry.
27///
28/// With a \b Declaration instance in place, constructors
29/// \alib{variables::Variable;Variable(Configuration& cfg, const Declaration* )}, as well as methods
30/// \alib{variables::Variable;Declare(const Declaration*)}, and
31/// \alib{variables::Variable;Try(const Declaration*)} can be used.
32///
33/// Nevertheless, as we will see below, a much nicer option exists.
34///
35/// \par Placeholders
36/// All fields support placeholders \c "%1", \c "%2" ... \c "%N", which are replaced with optional
37/// constructors of class \b %Variable, some of its methods \alib{variables::Variable;Declare}
38/// and with this classes' static method #Get.-
39///
40/// This allows defining a series of variables whose name, description, default value and
41/// comments are dependent on run-time information. For example, the text logging types of
42/// camp \alib_alox, have an own name. Now this name fills the placeholders within the variable
43/// declarations that each logger creates. This way, one resourced declaration is copied
44/// to be used by one or more loggers.
45///
46/// \par String Data Allocation
47/// The nature of this type's contained string data is "static" and "read only". Consequently
48/// this classes' members are simple \alib strings, without a own string buffer. The class relies
49/// on the fact that the lifecycle of the string data is permanent, just like C++ string literals
50/// that you might pass to the constructor, or like externalized resource strings, which is described
51/// in the next sections, are.<br>
52/// A little challenge arises when placeholders are used: Here, new string data has to be
53/// allocated. For this, the convenience method \alib{variables;Configuration::StoreDeclaration} is
54/// available. The method not only copies the data into the internal \alib{MonoAllocator},
55/// but it also checks if a corresponding replaced record was previously already stored. In this
56/// case no next copy is generated, but the old one is re-used.
57/// In the sample of \alox loggers above this means: The repeated creation and deletion of a
58/// logger with the same name generates only one declaration.
59///
60/// If a programmer provides self-generated variable names in combination with declarations,
61/// it has to be ensured that these variable names survive the lifecycle of the declaration.
62/// \note This is not true for the variable names of declared variables. They are duly copied,
63/// allocated, disposed, and recycled by class \b Configuration.
64///
65///
66/// \par Enum Records
67/// This type inherits class \alib{enumrecords::ERSerializable} and is enabled to be read from
68/// (externalized) resource data associated with C++ enumerations.
69/// The record associated with an enum element used for construction must be of this type itself.
70/// Consequently, equipping enum type \b MyEnum is performed like this:
71///
72/// ALIB_ENUMS_ASSIGN_RECORD( MyEnum, alib::variables::Declaration )
73///
74/// (For more information, see \ref alib_enums_records "ALib Enum Records".)
75///
76/// \par Resourced Enums
77/// Besides defining the enum record type, a custom enum has to have a specialization of the
78/// type traits \alib{resources;ResourcedTraits}.
79/// This is an exception to similar types found across \alib.
80/// Usually, a C++ enum type can be equipped with enum records and then optionally be resourced.
81/// The reason for this exception is that enum records of this type do load fields #DefaultValue and
82/// #Comments <em>indirectly</em> from resources by adding postfixes <b>_D</b>, respectively <b>_C</b>
83/// to the variable's resource name, along with the variable's underlying enumeration element's
84/// integral value.
85/// This way, both values are loaded from separated resource strings, which has the following
86/// advantages:
87/// - The values may contain the separation character used.
88/// - The values can be manipulated within the (externalized) resources more easily.
89///
90/// \note What was said here does not mean that \b Declaration instances have to be resourced.
91/// The point is that only if declarations are to be associated with C++ enums, which
92/// list the available variables, then this second step of resourcing the enums has
93/// to be made!
94///
95/// With these prerequisites in place, variables can be declared very conveniently by passing just
96/// a C++ enum element of custom enum type to one of the following methods:
97/// - Static method \alib{variables;Declaration::Get(TEnum)}
98/// - \alib{variables;Variable::Variable(Configuration&, TEnum)}
99/// - \alib{variables;Variable::Variable(Configuration&, TEnum, const Box)}
100/// - \alib{variables;Variable::Declare(TEnum)}
101/// - \alib{variables;Variable::Declare(TEnum, const Box&)}
102/// - \alib{variables::CampVariable(camp::Camp&, TEnum)}
103/// - \alib{variables::CampVariable(camp::Camp&, TEnum, const Box)}
104///
105/// Furthermore, a whole set of variables can be declared by passing just the enum type itself
106/// to method
107/// - \alib{variables;Configuration::PreloadVariables}.
108///
109/// This is usually done with bootstrap which makes all variables seamlessly available at least
110/// with a resourced default value, or overwritten by configuration files, CLI arguments or
111/// command lines. Usually the using code does not care and just accesses a variables
112/// value through the enumeration.
113///
114/// The resource data has to provide only three values in the following order:
115/// 1. The enum element value (this is mandatory with every resourced enum record).
116/// 2. Base class's field \alib{enumrecords;ERSerializable::EnumElementName}.
117/// \note Field \alib{enumrecords;ERSerializable::MinimumRecognitionLength} is not read from the string,
118/// but set to fixed value \c 0.
119/// 3. The typename.
120///
121/// As already noted above, fields #DefaultValue and #Comments can be defined in two separate
122/// resource strings named like the variable's resource itself with concatenated postfixes
123/// <b>_D</b>, respectively <b>_C</b> and the variable's underlying enumeration element's
124/// integral value. Both resources are optional and not mandatory to be existent.
125///
126/// A sample of variable resources is given with the
127/// \ref alib_ns_strings_propertyformatter_map_sample "documentation of class PropertyFormatter".
128///
129/// This makes it very convenient to have all attributes of a variable, including their name
130/// managed independently from the program code and allows localizing variable names to other
131/// languages. Of course, this applies to such variables only which become externalized.
132/// Therefore, this library likewise allows declaring and use variables without providing
133/// an instance of this type.
134///
135/// \par Reference Documentation
136/// \I{CLANGDUMMY}
137//==================================================================================================
139{
141 friend class alib::variables::Variable;
142
143 protected:
144 /// The type of the variable. Corresponds to what is defined with macros
145 /// \ref ALIB_VARIABLES_DEFINE_TYPE and ALIB_VARIABLES_REGISTER_TYPE.<br>
146 /// Built-in types are listed with chapter \ref alib_variables_types_builtin of the Programmer's
147 /// Manual.
149
150 /// The default value provided as an C++ string that may have to be parsed when imported into
151 /// a variable definition. If set, the variable becomes automatically defined with
152 /// \alib{variables;Priority;Priority::DefaultValues} when declared passing this instance.
153 /// @see Method #DefaultValue.
155
156 /// The configuration variable's comments.
157 /// \note
158 /// If the type trait \alib{resources;ResourcedTraits} is specialized for an
159 /// enumeration, this field is interpreted as a resource name to load the
160 /// description/comments from.
162
163 public:
164 /// Default constructor.
165 Declaration() = default;
166
167 //==============================================================================================
168 /// Constructor usually used with static variable declarations (declarations that are not
169 /// using enumeration types associated with \ref alib_enums_records "ALib Enum Records" of this
170 /// type).
171 ///
172 /// If used however to define an enum record during bootstrap of software (by user code
173 /// that omits the preferred option of parsing resourced strings to create such records), then
174 /// each parameter of type \b String passed, has to be of "static nature".
175 /// This means, that string buffers and their contents are deemed to survive the life-cycle of
176 /// an application. Usually, C++ string literals are passed in such situation.
177 ///
178 /// @param pName Value for field \alib{enumrecords;ERSerializable::EnumElementName}.
179 /// @param pTypeName Value for field #typeName.
180 /// @param pDefaultValue Value for field #defaultValue.
181 /// @param pComments Value for field #comments.
182 //==============================================================================================
183 Declaration( const String& pName, const String& pTypeName,
184 const String& pDefaultValue, const String& pComments )
185 : ERSerializable(pName )
186 , typeName (pTypeName )
187 , defaultValue (pDefaultValue )
188 , comments (pComments )
189 {}
190
191 /// Implementation of \alib{enumrecords;EnumRecordPrototype::Parse}.
192 /// \note Field \alib{enumrecords;ERSerializable::MinimumRecognitionLength} is not read from the
193 /// string, but set to fixed value \c 0.
195 void Parse();
196
197 //==============================================================================================
198 /// Static method that accepts an element of a C++ enum type equipped with
199 /// \ref alib_enums_records "ALib Enum Records" of this type, that contains the declaration data.
200 ///
201 /// In the case that a specialization of type trait \alib{resources;ResourcedTraits}
202 /// exists for the enumeration, #DefaultValue and #Comments are interpreted as a resource
203 /// name and are loaded with this method - separately from the resource pool.
204 ///
205 /// @tparam TEnum The custom enum type that is associated with variable declarations.
206 /// @param element The desired variable (aka element of type \p{TEnum}.
207 /// @return The resourced declaration associated with the given enumeration \p{element} of type
208 /// \p{TEnum}.
209 //==============================================================================================
210 template<typename TEnum>
211 requires (EnumRecords<TEnum>::template AreOfType<Declaration>())
212 static const Declaration* Get(TEnum element)
213 {
214 // get enum record singleton
215 const Declaration* result= &enumrecords::GetRecord(element);
216
217 // if resourced, check for default value and comments
218 #if ALIB_RESOURCES
219 if constexpr( resources::HasResources<TEnum>)
220 {
221 NString128 resName;
222 resName << resources::ResourcedTraits<TEnum>::Name() << "_D";
223 integer codePos = resName.Length() - 1;
224
225 // note: we need to do cast the const away. This is OK. We just did not have the
226 // possibility to get the resourced values right away with the record.
227 resName << UnderlyingIntegral( element );
228 const_cast<Declaration*>(result)->defaultValue = ResourcedType<TEnum>::Get( resName ALIB_DBG( , false ) );
229
230 resName[codePos] = 'C';
231 const_cast<Declaration*>(result)->comments = ResourcedType<TEnum>::Get( resName ALIB_DBG( , false ) );
232 }
233 #endif
234
235 return result;
236 }
237
238 /// Returns this configuration variable's type.
239 /// @return The name of this variable.
240 const String& TypeName() const { return typeName; }
241
242 /// Returns this configuration variable's name.
243 /// @return The name of this variable.
244 const String& Name() const { return EnumElementName; }
245
246 /// The default value provided as a C++ string (not escaped).
247 /// If provided, the variable becomes automatically defined with
248 /// \alib{variables;Priority;Priority::DefaultValues}.
249 ///
250 /// @return The contents of field #defaultValue.
251 const String& DefaultValue() const { return defaultValue; }
252
253 /// Returns this configuration variable's comments.
254 /// @return The comments of this variable.
255 const String& Comments() const { return comments; }
256
257}; // struct Declaration
258
259} // namespace alib::[config]
260
261/// Type alias in namespace \b alib.
263
264} // namespace [alib]
constexpr integer Length() const
Definition string.inl:318
const String & Comments() const
const String & DefaultValue() const
Declaration()=default
Default constructor.
static const Declaration * Get(TEnum element)
const String & TypeName() const
const String & Name() const
ALIB_DLL void Parse()
Definition vmeta.cpp:29
Declaration(const String &pName, const String &pTypeName, const String &pDefaultValue, const String &pComments)
#define ALIB_DLL
Definition alib.inl:496
#define ALIB_EXPORT
Definition alib.inl:488
#define ALIB_DBG(...)
Definition alib.inl:836
const RecordsTraits< TEnum >::Type & GetRecord(TEnum element)
Definition records.inl:188
NLocalString< 128 > NString128
Type alias name for TLocalString<nchar,128>.
variables::Declaration Declaration
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.
static const String & Get()