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