ALib C++ Framework
by
Library Version: 2605 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/// Copyright 2013-2026 A-Worx GmbH, Germany.
6/// Published under #"mainpage_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 #"FormatterPythonStyle::Sizes;*".
44/// - The use of this class within \alox configuration variable
45/// #"textlogger::FormatAutoSizes".
46//==================================================================================================
47class AutoSizes {
48
49 //################################################################################################
50 // Public fields
51 //################################################################################################
52 public:
53 /// The entry type, tab stop or field width.
54 enum class Types {
55 Tabstop, ///< denotes a tab stop entry.
56 Field, ///< denotes a field width entry.
57 };
58
59 /// The actual index requested by #".Next".
60 /// This field is reset to 0 with every invocation of #"Restart". The field is public and
61 /// may be read and manipulated, which is considered "expert use".
62 unsigned ActualIndex;
63
64 //################################################################################################
65 // Protected fields
66 //################################################################################################
67 protected:
68 /// Actual and current session entries of tab stop indexes, respectively field widths.
69 struct Entry {
70 Types type; ///< The type of entry.
71 integer actual; ///< The actually used value.
72 integer session; ///< The maximum value requested in the actual session.
73
74 /// Constructor.
75 /// @param t Value for field #".type".
76 /// @param v Value for field #".actual".
77 /// @param s Value for field #".session".
79 : type(t), actual(v), session(s) {}
80 }; // struct Entry
81
82 /// The current and measured sizes.
83 std::vector<Entry> data;
84
85 /// Determines whether any value was changed sincel last #".Reset".
86 bool dirty;
87
88 //################################################################################################
89 // Interface
90 //################################################################################################
91 public:
92 /// If set, method #".Actual" will not update the values, but instead return the requested
93 /// value.<br>
94 /// Defaults to \c false.
95 bool WriteProtected =false;
96
97 /// Resets all values, the current ones and the ones of the currently measured session, to
98 /// \c 0 and invokes #".Restart".
99 void Reset () { data.clear(); Restart(); dirty= true; }
100
101 /// Determines whether any value was changed since construction, or the last invocation of
102 /// methods #".Import", #".Export" or #".SetUnchanged".
103 /// @return \c true if any entry was changed, \c false otherwise.
104 bool IsChanged() const { return dirty; }
105
106 /// Same as #".IsChanged", but clears the internal flag.
107 /// @return \c true if any entry was changed, \c false otherwise.
108 bool SetUnchanged() { bool result= dirty; dirty= false; return result; }
109
110 /// Consolidates the values. This method is usually not invoked directly.
111 /// Instead, it is invoked with method #".Import".
112 /// The method loops through all values and copies the current session values to the actual
113 /// ones. The difference of both values is summed up during the loop and entries of type
114 /// #"Types::Tabstop" are adjusted by that difference.
115 /// As a result, the new values represent the smallest output format that fits all
116 /// rows, if the same output is performed as in the previous "session".
118 void Consolidate();
119
120 /// Initializes a new query sequence, which is a series of invocations of method #".Next".
121 /// @param startIdx The tab stop or field size position to continue with.
122 void Restart( unsigned startIdx= 0 ) { ActualIndex= startIdx; }
123
124 /// Returns the actual auto value stored, respectively, if the given requested size is
125 /// higher than what is stored, stores and returns the requested size.
126 ///
127 /// In the latter case, the given extra growth is added to the requested size, but only if
128 /// the value was set at least once before. In other words, the extra size is added only with
129 /// the second growth and each subsequent one.
130 ///
131 /// The requested size in addition replaces the current "session" value if it is higher than
132 /// the currently stored value. To this value, the growth padding is not added.
133 ///
134 /// The whole mechanism can be disabled by setting flag #".WriteProtected". If so, this
135 /// method just returns \p{requestedSize}
136 ///
137 /// If any of the values are changed, a call to #".IsChanged" will return \c true.
138 ///
139 /// @param type The type of entry.
140 /// @param requestedSize The minimum size that is requested.
141 /// @param growthPadding Added to the new size, if the requested size is greater than
142 /// the stored size and if the stored size does not equal \c -1.
143 ///
144 /// @return The (new) size of the auto field.
146 integer Actual( Types type, integer requestedSize, integer growthPadding );
147
148 /// Invokes #".Actual" and then increases the internal position counter.
149 ///
150 /// @param type The type of entry.
151 /// @param requestedSize The minimum size that is requested.
152 /// @param growthPadding Added to the new size if the requested size is greater than
153 /// the stored size and if the stored size does not equal \c -1.
154 ///
155 /// @return The (new) size of the auto field.
156 integer Next ( Types type, integer requestedSize, integer growthPadding ) {
157 auto result= Actual( type, requestedSize, growthPadding );
158 ++ActualIndex;
159 return result;
160 }
161
162 /// Imports values from the given #"^String" by parsing it.
163 /// Usually, string data are used for importing values was previously generated
164 /// with method #".Export".
165 ///
166 /// If parameter \p{session} equals #"CurrentData::Clear" (which is the default),
167 /// then after the import, method #".Consolidate" is invoked.
168 ///
169 /// \note
170 /// Parsing is 100% error-tolerant. If the given string does not contain what is expected
171 /// (see method #".Export"), then only a part or just nothing is imported.
172 /// This is due to the purpose of this class, which is to allow nicer, tabbed output.
173 /// If this is not possible due to import problems, the system should work normally still.
174 /// With debug-builds, a #"alib_mod_assert;warning is raised" in this case.
175 ///
176 /// This method clears the internal flag that tracks changes, hence after an invocation,
177 /// #".IsChanged" returns \c false.
178 ///
179 /// @param source The #"%^String" that is parsed for the exported data.
180 /// @param session Denotes if #".Consolidate" is to be invoked after import.
181 /// Defaults to #"CurrentData::Clear", which performs
182 /// consolidation.
184 void Import( const String& source, lang::CurrentData session= lang::CurrentData::Clear );
185
186 /// Exports the current session values by serializing the stored values into to the given
187 /// #"^AString" object.
188 ///
189 /// For each current entry in this object, <c>"T|F Actual[,session]"</c> is written,
190 /// separated by a forward slash <c>'/'</c>. The session value is written only in case
191 /// it differs from the actual value.
192 /// Furthermore, if field #".WriteProtected" is set, an exclamation mark <c>'!'</c> will be
193 /// written as a first character. With that, the complete syntax is:
194 ///
195 /// [!] [ T|F Actual[,session] ] [/ T|F Actual[,session] ]
196 ///
197 /// This method clears the internal flag that tracks changes, hence after an invocation,
198 /// #".IsChanged" returns \c false.
199 ///
200 /// @param target The #"%AString" to receive the our values.
202 void Export( AString& target );
203};
204
205
206}} // namespace alib[::strings::util]
207
208
209/// Type alias in namespace #"%alib".
211
212} // namespace [alib]
#define ALIB_DLL
#define ALIB_EXPORT
integer Actual(Types type, integer requestedSize, integer growthPadding)
Definition autosizes.cpp:4
void Export(AString &target)
Definition autosizes.cpp:38
bool dirty
Determines whether any value was changed sincel last #".Reset".
Definition autosizes.hpp:86
void Import(const String &source, lang::CurrentData session=lang::CurrentData::Clear)
Definition autosizes.cpp:66
void Restart(unsigned startIdx=0)
std::vector< Entry > data
The current and measured sizes.
Definition autosizes.hpp:83
Types
The entry type, tab stop or field width.
Definition autosizes.hpp:54
@ Tabstop
denotes a tab stop entry.
Definition autosizes.hpp:55
integer Next(Types type, integer requestedSize, integer growthPadding)
@ Clear
Chooses to clear existing data.
Definition alox.cpp:14
strings::util::AutoSizes AutoSizes
Type alias in namespace #"%alib".
lang::integer integer
Type alias in namespace #"%alib".
Definition integers.hpp:149
strings::TField< character > Field
Type alias in namespace #"%alib".
strings::TString< character > String
Type alias in namespace #"%alib".
Definition string.hpp:2165
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace #"%alib".
integer actual
The actually used value.
Definition autosizes.hpp:71
Entry(Types t, integer v, integer s)
Definition autosizes.hpp:78
integer session
The maximum value requested in the actual session.
Definition autosizes.hpp:72