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