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