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