ALib C++ Library
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
propertyformatters.mpp
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of the \aliblong.
4/// With supporting legacy or module builds, .mpp-files are either recognized by the build-system
5/// as C++20 Module interface files, or are included by the
6/// \ref alib_manual_modules_impludes "import/include headers".
7///
8/// \emoji :copyright: 2013-2025 A-Worx GmbH, Germany.
9/// Published under \ref mainpage_license "Boost Software License".
10//==================================================================================================
11#if !defined(ALIB_C20_MODULES) || ((ALIB_C20_MODULES != 0) && (ALIB_C20_MODULES != 1))
12# error "Symbol ALIB_C20_MODULES has to be given to the compiler as either 0 or 1"
13#endif
14#if ALIB_C20_MODULES
15 module;
16#endif
17//========================================= Global Fragment ========================================
18#include "alib/alib.inl"
19#if ALIB_VARIABLES
20# include <unordered_map>
21#endif
22//============================================== Module ============================================
23#if ALIB_C20_MODULES
24 /// This is a <em><b>C++ Module</b></em> of the \aliblong.
25 /// Due to the dual-compile option (either as C++20 Modules or using legacy C++ inclusion),
26 /// the C++20 Module names are not of further interest or use.<br>
27 /// In general, the names equal the names of the header files listed in the chapter
28 /// \ref alib_manual_modules_impludes of the \alib User Manual.
29 ///
30 /// @see The documentation of the <em><b>"ALib Module"</b></em> given with the corresponding
31 /// Programmer's Manual \alib_format.
32 export module ALib.Format.PropertyFormatters;
33 #if ALIB_VARIABLES
34 import ALib.Lang;
35 import ALib.Strings;
36 import ALib.EnumRecords;
37 import ALib.Exceptions;
38 import ALib.Format;
39 import ALib.Format.PropertyFormatter;
40 import ALib.Variables;
41 #endif
42#else
43# if ALIB_VARIABLES
44 #include "ALib.Lang.H"
45 #include "ALib.Strings.H"
46 #include "ALib.EnumRecords.H"
47 #include "ALib.Exceptions.H"
48 #include "ALib.Format.H"
50 #include "ALib.Variables.H"
51# endif
52#endif
53
54//============================================= Exports ============================================
55#if ALIB_VARIABLES
56ALIB_EXPORT namespace alib { namespace format {
57
58//==================================================================================================
59/// # Introduction # {#alib_ns_strings_propertyformatter_map_overview}
60///
61/// This template class provides a map of \alib{format;PropertyFormatter} objects that use
62/// format strings which are defined by variables of a \alib{variables;Configuration}.
63///
64/// The use case is about having different versions of how an object is formatted and
65/// to have these versions configurable to end users through the \alib variable system.
66///
67///\I{##############################################################################################}
68/// # Sample # {#alib_ns_strings_propertyformatter_map_sample}
69/// The concept is best explained by a code sample. From the documentation of class
70/// \alib{format;PropertyFormatter}, we are using the sample setup:
71///
72/// \snippet "DOX_STRINGS.cpp" DOX_STRINGS_PROPERTY_FORMATTER_1
73/// \snippet "DOX_STRINGS.cpp" DOX_STRINGS_PROPERTY_FORMATTER_2
74/// \snippet "DOX_STRINGS.cpp" DOX_STRINGS_PROPERTY_FORMATTER_3
75///
76/// Three different output formats, \e Short, \e Default and \e All should be supported
77/// We define an enumeration type for this purpose and use macro \ref ALIB_ENUMS_ASSIGN_RECORD
78/// to equip the enumeration with \ref alib_enums_records "ALib Enum Records" of type
79/// \alib{variables;Declaration}.
80/// In addition, macro \ref ALIB_RESOURCED is used to announce that the record data is defined using
81/// resourced string data.
82///
83/// \snippet "DOX_STRINGS.cpp" DOX_STRINGS_PROPERTY_FORMATTER_MAP_1
84///
85/// The following piece of code is to be performed during
86/// \ref alib_mod_bs "bootstrapping".
87/// We take the freedom to use the resource pool of camp \alib{camp;Basecamp}:
88/// \snippet "DOX_STRINGS.cpp" DOX_STRINGS_PROPERTY_FORMATTER_MAP_2
89///
90/// \note
91/// The default value and variable comment string can be saved when we write back the variables
92/// to a configuration file. This hints users to the fact that the output format is changeable,
93/// i.e., when they open an INI-file. See chapter \ref alib_variables_external_ini of the Programmer's
94/// Manual of camp \alib_variables for information about how to write built-in default variables like
95/// this to an external configuration file.
96///
97/// In the next phase of bootstrapping, our enumeration records have to be initialized from the
98/// resource pool:
99///
100/// \snippet "DOX_STRINGS.cpp" DOX_STRINGS_PROPERTY_FORMATTER_MAP_22
101///
102/// With this in place, the \b %PropertyFormatters can be created and method
103/// #Format can be used:
104///
105/// \snippet "DOX_STRINGS.cpp" DOX_STRINGS_PROPERTY_FORMATTER_MAP_31
106///
107/// But we're still not fully done yet: The next goal is to have a lightweight object that is
108/// \"\alib{strings;AppendableTraits;appendable}\" to objects of class
109/// \alib{strings;TAString;AString}.
110/// Such object is given with template type \alib{format;PropertyFormatterMapAppendable}.
111/// It is a simple helper-struct that holds a reference to the formatter map, the format enumeration
112/// value and the object to format.<br>
113/// We define a shortcut to the type with the right template arguments in place:
114/// \snippet "DOX_STRINGS.cpp" DOX_STRINGS_PROPERTY_FORMATTER_MAP_32
115///
116/// Now, we are set and can start using the formatter:
117/// \snippet "DOX_STRINGS.cpp" DOX_STRINGS_PROPERTY_FORMATTER_MAP_4
118///
119/// Running the code above produces the following output:
120/// \verbinclude "DOX_STRINGS_PROPERTY_FORMATTER_MAP.txt"
121///
122/// To make the code even shorter, macros may be used:
123/// \snippet "DOX_STRINGS.cpp" DOX_STRINGS_PROPERTY_FORMATTER_MAP_5
124///
125/// The output is:
126/// \verbinclude "DOX_STRINGS_PROPERTY_FORMATTER_MAP_2.txt"
127///
128///\I{#############################################################################################}
129/// # Using The Appendable With Formatters # {#alib_ns_strings_propertyformatter_map_usingwithfmts}
130/// The sample above showcased how to \ref alib_strings_assembly_ttostring "append" a lightweight
131/// object of helper-class \alib{format;PropertyFormatterMapAppendable} to objects of class
132/// \alib{strings;TAString;AString}.
133/// A final step is to define the \ref alib::boxing "boxing" interface
134/// \alib{boxing;FAppend} to make boxed objects of our helper-type applicable. As the type
135/// itself is already appendable, we can use a built-in simple macro for that:
136///
137/// \snippet "DOX_STRINGS.cpp" DOX_STRINGS_PROPERTY_FORMATTER_MAP_6
138///
139/// As described in the Programmer's Manual of module \alib_boxing, such interface definition
140/// should be done only once and be placed in the bootstrap section of a process.
141///
142/// With this, using formatters in combination with our helper-struct works fine:
143/// \snippet "DOX_STRINGS.cpp" DOX_STRINGS_PROPERTY_FORMATTER_MAP_7
144///
145/// This code produces the following output.
146/// \verbinclude "DOX_STRINGS_PROPERTY_FORMATTER_MAP_3.txt"
147///
148///\I{#############################################################################################}
149/// # Module Dependencies #
150/// This class is only available if module \alib_variables is included in the \alibbuild.
151///
152///\I{#############################################################################################}
153/// # Reference Documentation #
154/// @throws alib::format::FMTExceptions::MissingConfigurationVariable \I{CLANGDUMMY}
155///
156/// @tparam TFormattable The type that is formatted.
157/// @tparam TVariables The enumeration of variables which defines the format strings.
158//==================================================================================================
159template<typename TFormattable, typename TVariables >
161{
162 protected:
163 /// The callback table for the property formatters (as given in the constructor).
165
166 /// The configuration used to load (and store the default) format strings from.
168
169 /// The map of formatters
170 std::unordered_map<TVariables, PropertyFormatter*> formatters;
171
172 public:
173 /// The formatter (as given in the constructor).
175
176 public:
177 /// Constructor storing arguments in fields.
178 /// All variables are declared within the given \p{configuration} and defined with their
179 /// default values given with their declaration records (associated with \p{TVariables})
180 /// and thus - if exported to a write-enabled external configuration source like,
181 /// for example, \alib{variables;IniFileFeeder} - can be noted by the end-user to be
182 /// configurable.
183 ///
184 /// Parameter \p{formatter} defaults to \c nullptr, which causes this constructor to create
185 /// a clone of the static formatter given with \alib{format;Formatter::Default}.
186 /// Note, that this is in contrast to the similar parameter of class
187 /// \alib{format;PropertyFormatter}, which uses the default formatter itself
188 /// in the case that \c nullptr is provided. The rationale behind creating a copy is that
189 /// it is quite likely that the \b %PropertyFormatter objects created here are used
190 /// nested within other format operations. This is especially true with the use of helper
191 /// struct \alib{format;PropertyFormatterMapAppendable}. Now, nested formatting must
192 /// not be done with the same formatter object.
193 ///
194 ///
195 /// @param callbackTable The callback table as specified with
196 /// \alib{format;PropertyFormatter::TCallbackTable}.
197 /// @param configuration The configuration to load the format strings from (and to store
198 /// the default values defined by the enum record of \p{TVariables}).
199 /// @param formatter The underlying formatter. Used for construction of
200 /// \alib{format;PropertyFormatter}s.<br>
201 /// Defaults to \c nullptr which denotes to create a copy of the
202 /// static formatter given with \alib{format;Formatter::Default}.
204 variables::Configuration& configuration,
205 SPFormatter formatter = nullptr )
206 : callbacks( callbackTable )
207 , config ( configuration )
208 , Formatter( formatter )
209 {
210 if ( Formatter == nullptr )
212
213 for( auto recordIt= EnumRecords<TVariables>().begin() ;
214 recordIt != EnumRecords<TVariables>().end() ; ++recordIt )
215 {
216 Variable var(config, recordIt.Enum() );
217 }
218 }
219
220 /// Destructor. Deletes the \alib{format;PropertyFormatter}s which got created.
222 {
223 for( auto& formatter : formatters )
224 delete formatter.second;
225 }
226
227 /// Chooses or - if not yet available - creates the right \alib{format;PropertyFormatter}
228 /// and invokes its method \alib{format;PropertyFormatter::Format;Format}.
229 ///
230 /// @param target The target string to write into.
231 /// @param option The user-defined formatting option.
232 /// @param formattable The custom object which is passed to the callback methods to collect
233 /// the formatter arguments.
234 void Format( AString& target, TVariables option, TFormattable& formattable )
235 {
236 auto formatter= formatters.find( option );
237 if( formatter == formatters.end() )
238 {
239 // find option in the table
240 for( auto varEntryIt= EnumRecords<TVariables>().begin() ;
241 varEntryIt != EnumRecords<TVariables>().end() ; ++varEntryIt )
242 if( varEntryIt.Enum() == option )
243 {
244 Variable vc(config, varEntryIt.Enum() );
245 if( vc.GetPriority() == Priority::NONE
246 || vc.GetString().IsEmpty() )
247 {
249 String256(vc) );
250 }
251 formatter= formatters.emplace(
252 std::make_pair( option,
254 ).first;
255 break;
256 }
257
258 ALIB_ASSERT_ERROR( formatter != formatters.end(), "FORMAT",
259 "No entry for option {!Q<>} found in option table of PropertyFormatters.",
260 static_cast<std::underlying_type_t<TVariables>>(option) )
261 }
262
263 formatter->second->Format( target, formattable );
264 }
265
266}; // class PropertyFormatters
267
268/// Helper-struct for users of class \alib{format;PropertyFormatters}.
269/// Objects of this type are \alib{strings;AppendableTraits;appendable} to \b %AStrings.
270///
271/// A custom using statement should be used to access this type in a very short fashion,
272/// to make "applications" to \b %AStrings a short call. Alternatively one ore more preprocessor
273/// macros might even lead to shorter invocations. (See sample in class description).
274
275template<typename TFormattable, typename TOptionEnum >
277{
279 TOptionEnum Option; ///< The format option defining the
280 ///< \alib{format;PropertyFormatter} used.
281 TFormattable& Formattable; ///< The object to be formatted.
282
283
284 /// Constructor. Just saves the given parameters.
285 /// @param pFormatterMap The \alib{format;PropertyFormatters} to use.
286 /// @param pOption The format option defining the
287 /// \alib{format;PropertyFormatter} used.
288 /// @param pFormattable The object to be formatted.
290 TOptionEnum pOption,
291 TFormattable& pFormattable )
292 : FormatterMap(pFormatterMap)
293 , Option(pOption)
294 , Formattable(pFormattable)
295 {}
296}; // struct PropertyFormatterMapAppendable
297
298
299//##################################################################################################
300// ##### AppendableTraits specialization
301//##################################################################################################
302
303} namespace strings {
304
305#if DOXYGEN
306 namespace APPENDABLES { // Documentation fake namespace
307#endif
308
309/// Specialization of functor \alib{strings;AppendableTraits} for helper-struct
310/// \b %PropertyFormatterMapAppendable used to format objects with
311/// \alib{format;PropertyFormatters}.
312/// @tparam TFormattable The formattable object type.
313/// @tparam TOptionEnum The format option enumeration type.
314template<typename TFormattable, typename TOptionEnum >
315struct AppendableTraits<typename format::PropertyFormatterMapAppendable<TFormattable,TOptionEnum>, character, lang::HeapAllocator>
316{
317 /// Invokes the \alib{format;PropertyFormatters::Format} of the formatter map
318 /// encapsulated in \p{src}.
319 /// @param target The target string.
320 /// @param src The helper-struct object.
325};
326
327/// Specialization of functor \alib{strings;AppendableTraits} for pointers to helper-struct
328/// \b %PropertyFormatterMapAppendable used to format objects with
329/// \alib{format;PropertyFormatters}.
330/// @tparam TFormattable The formattable object type.
331/// @tparam TOptionEnum The format option enumeration type.
332template<typename TFormattable, typename TOptionEnum >
333struct AppendableTraits<typename format::PropertyFormatterMapAppendable<TFormattable,TOptionEnum>*, character, lang::HeapAllocator>
334{
335 /// Invokes the \alib{format;PropertyFormatters::Format} of the formatter map
336 /// encapsulated in \p{src}.
337 /// @param target The target string.
338 /// @param src Pointer to the helper-struct object.
343};
344
345#if DOXYGEN
346} // APPENDABLES documentation fake namespace
347#endif
348
349} // namespace alib[::strings]
350
351
352/// Type alias in namespace \b alib.
353template<typename TFormattable, typename TOptionEnum >
355
356} // namespace [alib]
357
358#endif // ALIB_VARIABLES
static ALIB_DLL SPFormatter Default
std::vector< IdentifierEntry > TCallbackTable
Type definition of the callback table.
PropertyFormatters(typename PropertyFormatter::TCallbackTable &callbackTable, variables::Configuration &configuration, SPFormatter formatter=nullptr)
~PropertyFormatters()
Destructor. Deletes the PropertyFormatters which got created.
std::unordered_map< TOptionEnum, PropertyFormatter * > formatters
void Format(AString &target, TVariables option, TFormattable &formattable)
constexpr bool IsEmpty() const
Definition string.inl:365
#define ALIB_CALLER_NULLED
Definition alib.inl:1027
#define ALIB_EXPORT
Definition alib.inl:497
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1066
LocalString< 256 > String256
Type alias name for TLocalString<character,256>.
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace alib.
variables::Variable Variable
Type alias in namespace alib.
format::PropertyFormatters< TFormattable, TOptionEnum > PropertyFormatters
Type alias in namespace alib.
enumrecords::EnumRecords< TEnum > EnumRecords
Type alias in namespace alib.
Definition records.inl:482
format::PropertyFormatter PropertyFormatter
Type alias in namespace alib.
exceptions::Exception Exception
Type alias in namespace alib.
containers::SharedPtr< format::Formatter > SPFormatter
Definition formatter.inl:42
characters::character character
Type alias in namespace alib.
TFormattable & Formattable
The object to be formatted.
PropertyFormatterMapAppendable(PropertyFormatters< TFormattable, TOptionEnum > &pFormatterMap, TOptionEnum pOption, TFormattable &pFormattable)
PropertyFormatters< TFormattable, TOptionEnum > & FormatterMap
The formatter map to use.
void operator()(TAString< character, lang::HeapAllocator > &target, const typename format::PropertyFormatterMapAppendable< TFormattable, TOptionEnum > *src)
void operator()(TAString< character, lang::HeapAllocator > &target, const typename format::PropertyFormatterMapAppendable< TFormattable, TOptionEnum > &src)