ALib C++ Library
Library Version: 2412 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
autosizes.hpp
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header file is part of module \alib_strings of the \aliblong.
4///
5/// \emoji :copyright: 2013-2024 A-Worx GmbH, Germany.
6/// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8#ifndef HPP_ALIB_STRINGS_UTIL_AUTOSIZES
9#define HPP_ALIB_STRINGS_UTIL_AUTOSIZES 1
10#pragma once
12#include <vector>
13
14namespace alib { namespace strings { namespace util {
15
16//==================================================================================================
17/// This class stores and manages tabulator positions and field sizes. The class supports a
18/// simple session handling, by storing each value once for the actual output session and a
19/// second time for a future session. The motivation for writing this class came from the
20/// requirements of logging library \alib_alox. The goals here are:
21///
22/// - During a logging session, log output should be as much tabular as possible.
23/// - On the same time, the log output should be as "narrow" as possible.
24///
25/// If used correctly, this class helps to achieve the following:
26/// - A new log-output session increases tab stops and field widths during execution as needed.
27/// - If values need to be increased, a certain amount of "extra padding" might be
28/// added to avoid too many small increments.
29/// - Once all tab stops or fields have been logged with values of their maximum size, the log output
30/// will not vary in respect to tab stops and auto-sizes anymore.
31/// - If a subsequent session contains the very same log-output (aka the same maximum of requested
32/// tab positions and field width), all extra space is removed and the log output is 100% tabular
33/// beginning with the session start.
34/// - If a subsequent session contains smaller values, then this session is formatted with the
35/// (still larger) width of the previous session. After that, the next session will use the smaller
36/// sizes.
37///
38/// This approach very well guarantees stable log output widths across sessions. Only if the
39/// execution path of software changes (or logging verbosity setting is changed), adjustments
40/// are performed.
41///
42/// To preserve the information across <em>sessions</em>, this class provides methods to transform
43/// its information from and to string representations which can be stored in configuration files.
44///
45/// As the use case of this class is not restricted to log output, but can be used in general when
46/// working with strings, it became a utility class of module \alib_strings_nl.
47///
48/// @see
49/// - The use of this class with field \alib{lang::format;FormatterPythonStyle::Sizes}.
50/// - The use of this class within \alox configuration variable
51/// \alib{lox::textlogger;FormatAutoSizes}.
52//==================================================================================================
54{
55
56 // #############################################################################################
57 // Public fields
58 // #############################################################################################
59 public:
60 /// The entry type, tab stop or field width.
61 enum class Types
62 {
63 Tabstop, ///< denotes a tab stop entry.
64 Field, ///< denotes a field width entry.
65 };
66
67 /// The actual index requested by #Next.
68 /// This field is reset to 0 with every invocation of #Start. The field is public and
69 /// may be read and manipulated, which is considered "expert use".
70 unsigned int ActualIndex;
71
72 // #############################################################################################
73 // Protected fields
74 // #############################################################################################
75 protected:
76 /// Actual and current session entries of tab stop indexes, respectively field widths.
77 struct Entry
78 {
79 Types type; ///< The type of entry.
80 integer actual; ///< The actually used value.
81 integer session; ///< The maximum value requested in the actual session.
82
83 /// Constructor.
84 /// @param t Value for field #type.
85 /// @param v Value for field #actual.
86 /// @param s Value for field #session.
88 : type(t), actual(v), session(s)
89 {}
90 }; // struct Entry
91
92 /// The current and measured sizes.
93 std::vector<Entry> data;
94
95 /// Determines whether any value was changed sincel last #Reset.
96 bool dirty;
97
98 // #############################################################################################
99 // Interface
100 // #############################################################################################
101 public:
102 /// If set, method #Actual will not update the values, but instead return the requested
103 /// value.<br>
104 /// Defaults to \c false.
105 bool WriteProtected = false;
106
107 /// Resets all values, the current ones and the ones of the currently measured session, to
108 /// \c 0 and invokes #Restart().
109 void Reset () { data.clear(); Restart(); dirty= true; }
110
111 /// Determines whether any value was changed since construction, or the last invocation of
112 /// methods #Import, #Export or #SetUnchanged.
113 /// @return \c true if any entry was changed, \c false otherwise.
114 bool IsChanged() const { return dirty; }
115
116 /// Same as #IsChanged(), but clears the internal flag.
117 /// @return \c true if any entry was changed, \c false otherwise.
118 bool SetUnchanged() { bool result= dirty; dirty= false; return result; }
119
120 //==========================================================================================
121 /// Consolidates the values. This method is usually not invoked directly.
122 /// Instead, it is invoked with method #Import.
123 /// The method loops through all values and copies the current session values to the actual
124 /// ones. The difference of both values is summed up during the loop and entries of type
125 /// \alib{strings::util::AutoSizes;Types::Tabstop} are adjusted by that difference.
126 /// As a result, the new values represent the smallest output format that fits all
127 /// rows, if the same output is performed as in the previous "session".
128 //==========================================================================================
130 void Consolidate();
131
132 //==========================================================================================
133 /// Initializes a new query sequence, which is a series of invocations of method #Next.
134 /// @param startIdx The tab stop or field size position to continue with.
135 //==========================================================================================
136 void Restart( unsigned int startIdx= 0 ) { ActualIndex= startIdx; }
137
138 //==========================================================================================
139 /// Returns the actual auto value stored, respectively, if the given requested size is
140 /// higher than what is stored, stores and returns the requested size.
141 ///
142 /// In the latter case, the given extra growth is added to the requested size, but only if
143 /// the value was set at least once before. In other words, the extra size is added only with
144 /// the second growth and each subsequent one.
145 ///
146 /// The requested size in addition replaces the current "session" value if it is higher than
147 /// the currently stored value. To this value, the growth padding is not added.
148 ///
149 /// The whole mechanism can be disabled by setting flag #WriteProtected. If so, this
150 /// method just returns \p{requestedSize}
151 ///
152 /// If any of the values are changed, a call to #IsChanged will return \c true.
153 ///
154 /// @param type The type of entry.
155 /// @param requestedSize The minimum size that is requested.
156 /// @param growthPadding Added to the new size, if the requested size is greater than
157 /// the stored size and if the stored size does not equal \c -1.
158 ///
159 /// @return The (new) size of the auto field.
160 //==========================================================================================
162 integer Actual( Types type, integer requestedSize, integer growthPadding );
163
164 //==========================================================================================
165 /// Invokes #Actual and then increases the internal position counter.
166 ///
167 /// @param type The type of entry.
168 /// @param requestedSize The minimum size that is requested.
169 /// @param growthPadding Added to the new size if the requested size is greater than
170 /// the stored size and if the stored size does not equal \c -1.
171 ///
172 /// @return The (new) size of the auto field.
173 //==========================================================================================
174 integer Next ( Types type, integer requestedSize, integer growthPadding )
175 {
176 auto result= Actual( type, requestedSize, growthPadding );
177 ++ActualIndex;
178 return result;
179 }
180
181 //==========================================================================================
182 /// Imports values from the given \alib{strings;TString;String} by parsing it.
183 /// Usually, string data are used for importing values was previously generated
184 /// with method #Export.
185 ///
186 /// If parameter \p{session} equals \alib{lang::CurrentData;Clear} (which is the default),
187 /// then after the import, method #Consolidate is invoked.
188 ///
189 /// \note
190 /// Parsing is 100% error-tolerant. If the given string does not contain what is expected
191 /// (see method #Export), then only a part or just nothing is imported.
192 /// This is due to the purpose of this class, which is to allow nicer, tabbed output.
193 /// If this is not possible due to import problems, the system should work normally still.
194 /// With debug-builds, an \ref ALIB_WARNING is written in this case.
195 ///
196 /// This method clears the internal flag that tracks changes, hence after an invocation,
197 /// #IsChanged returns \c false.
198 ///
199 /// @param source The \b %String that is parsed for the exported data.
200 /// @param session Denotes if #Consolidate is to be invoked after import.
201 /// Defaults to \alib{lang::CurrentData;Clear}, which performs
202 /// consolidation.
203 //==========================================================================================
205 void Import( const String& source, lang::CurrentData session= lang::CurrentData::Clear );
206
207 //==========================================================================================
208 /// Exports the current session values by serializing the stored values into to the given
209 /// \alib{strings;TAString;AString} object.
210 ///
211 /// For each current entry in this object, <c>"T|F Actual[,session]</c> is written,
212 /// separated by a forward slash <c>'/'</c>. The session value is written only in case
213 /// it differs from the actual value.
214 /// Furthermore, if field #WriteProtected is set, an exclamation mark <c>'!'</c> will be
215 /// written as a first character. With that, the complete syntax is:
216 ///
217 /// [!] [ T|F Actual[,session] ] [/ T|F Actual[,session] ]
218 ///
219 /// This method clears the internal flag that tracks changes, hence after an invocation,
220 /// #IsChanged returns \c false.
221 ///
222 /// @param target The \b %AString to receive the our values
223 //==========================================================================================
225 void Export( AString& target );
226};
227
228
229}} // namespace alib[::strings::util]
230
231
232/// Type alias in namespace \b alib.
234
235} // namespace [alib]
236
237#endif // HPP_ALIB_STRINGS_UTIL_AUTOSIZES
238
std::vector< Entry > data
The current and measured sizes.
Definition autosizes.hpp:93
void Restart(unsigned int startIdx=0)
ALIB_API void Import(const String &source, lang::CurrentData session=lang::CurrentData::Clear)
Definition autosizes.cpp:88
Types
The entry type, tab stop or field width.
Definition autosizes.hpp:62
@ Field
denotes a field width entry.
@ Tabstop
denotes a tab stop entry.
ALIB_API integer Actual(Types type, integer requestedSize, integer growthPadding)
Definition autosizes.cpp:19
ALIB_API void Export(AString &target)
Definition autosizes.cpp:58
integer Next(Types type, integer requestedSize, integer growthPadding)
bool dirty
Determines whether any value was changed sincel last Reset.
Definition autosizes.hpp:96
#define ALIB_API
Definition alib.hpp:639
@ Clear
Chooses to clear existing data.
Definition alib.cpp:69
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:273
Actual and current session entries of tab stop indexes, respectively field widths.
Definition autosizes.hpp:78
integer session
The maximum value requested in the actual session.
Definition autosizes.hpp:81
Entry(Types t, integer v, integer s)
Definition autosizes.hpp:87
integer actual
The actually used value.
Definition autosizes.hpp:80