ALib C++ Framework
by
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
inifilefeeder.inl
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_variables of the \aliblong.
4///
5/// \emoji :copyright: 2013-2025 A-Worx GmbH, Germany.
6/// Published under #"mainpage_license".
7//==================================================================================================
8ALIB_EXPORT namespace alib { namespace variables {
9
10//==================================================================================================
11/// Adapter type between class #"IniFile" and class #"Configuration".
12/// INI-Files contents usually are fed in with bootstrapping an application and optionally be
13/// written out when an application ends (to populate empty INI-files or add new variables to
14/// existing ones). For this, an instance of this type is to be created locally each time. In other
15/// words, no instance of this type needs to be kept in memory during the life-span of an
16/// application.
17/// @see Chapter #"alib_variables_external_ini" of the Programmer's Manual of camp \alib_variables.
18/// @throws alib::variables::Exceptions::ErrorWritingFile \I{CLANGDUMMY}
19//==================================================================================================
21{
22 //=========================================== Internals ==========================================
23 protected:
24 /// The configuration to work with. Set with construction.
26
27 /// The priority to use to define variables. Set with construction.
29
30 /// The INI-file. Created with methods #"ImportStart" and #"ExportStart".
31 IniFile* iniFile = nullptr;
32
33 /// Implements overloaded methods #".ImportSection(const String&)".
34 /// @param section The section to import
35 /// @return The number of variables imported.
37 int importSection( IniFile::Section& section );
38
39
40 //========================================= Public Fields ========================================
41 public:
42 /// The desired maximum width of the INI-file. Defaults to <c>100</c>.
43 /// This value is used with utility method #".AddResourcedSectionComments(ResourcePool&)".
44 int LineWidth = 100;
45
46 /// The prefix that is used for comment lines of sections or variables that have been
47 /// added 'in code' (variables that have not been read from the file).
48 /// Comments that were read from the file preserve their prefix.
49 /// If comments including one of the valid prefixes are added to a variable or section
50 /// 'in code', such prefix is preserved.
52
53 /// This flag may be read after invoking the method #"ExportStart", which will try to
54 /// read the file first. If the file could not be opened or is empty, this flag is set.
55 /// The flag may be used to decide, for example, if a file-comment or section comments
56 /// should be generated.
58
59
60 //==================================== Constructors/destructor ===================================
61 public:
62 /// Constructor.
63 /// @param pConfiguration Stored in the field #"configuration".
64 /// @param pPriority Stored in the field #".priority". Defaults to #"Priority::ConfigFile".
65 ///
66 IniFileFeeder( Configuration& pConfiguration, Priority pPriority= Priority::ConfigFile )
67 : configuration(pConfiguration)
68 , priority (pPriority) {}
69
70 /// Virtual destructor. #"alib_mod_assert;Raises an ALib warning" in debug-compilations,
71 /// if the internal INI-file was not disposed before deletion. Disposal is made with methods
72 /// #"ImportEnd" and ExportEnd.
73 virtual ~IniFileFeeder() {
74 #if ALIB_DEBUG && !ALIB_DEBUG_ASSERTION_PRINTABLES
75 ALIB_ASSERT_WARNING(iniFile == nullptr, "VARIABLES",
76 "Export or import sequence not completed before deleting the INI-file.\n"
77 "Filename of previous sequence: {}", iniFile->FileName )
78 delete iniFile;
79 #endif
80
81 }
82
83 //=========================================== Interface ==========================================
84 /// Imports all entries in the section named \p{sectionName} in the underlying INI-file into
85 /// the configuration.
86 /// @param sectionName The name of the section to import.
87 /// @return The number of variables imported.
89 int ImportSection( const String& sectionName );
90
91 /// Imports all entries in the section named \p{sectionName} in the underlying INI-file into
92 /// the configuration. This special version of the method accepts parameter \p{typeName}
93 /// and hence declares the variables in case they have not been declared, yet.
94 ///
95 /// \note
96 /// This method is useful to load a section of variables of the same type with a) avoiding to
97 /// set preset string and b) with the advantage that a using code may use
98 /// #"Variable::Try(const String&);Variable::Try" to find the variable without declaring
99 /// it.<br>
100 /// This method may be used, for example, with camp \alib_expressions to declare nested
101 /// expressions to an #"StandardRepository".
102 /// @param sectionName The name of the section to import.
103 /// @param typeName The type of the variable to declare.
104 /// @return The number of variables imported.
106 int ImportSection( const String& sectionName, const String& typeName );
107
108 /// Imports all entries found INI-file into the configuration. Variables which are already
109 /// declared and have a lower priority definition, will be set with the value found.
110 /// Otherwise, a #"PresetImportString(StringEscaper);preset string" is set for the
111 /// variable.
112 /// @return The number of variables imported.
114 int ImportAll();
115
116 /// Creates the internal \p{iniFile} instance.
117 /// @param path The filepath to the INI-file.
118 /// @return The number of entries read. (The result of method #"IniFile::Read;*".)
119 int ImportStart( const system::Path& path ) {
120 if( iniFile != nullptr ) {
121 ALIB_ASSERT_WARNING(iniFile == nullptr, "VARIABLES",
122 "Export or import sequence not completed before starting a new one.\n"
123 "Previous filename: ", iniFile->FileName )
124 delete iniFile;
125 }
126 iniFile= new IniFile();
127 return iniFile->Read(path);
128 }
129
130 /// Creates the internal \p{iniFile} instance.
131 /// @param path The filepath to the INI-file.
132 /// @return The number of entries read. (The result of method #"IniFile::Read;*".)
133 int ExportStart( const system::Path& path ) {
134 int qtyEntries= 0;
135 try { qtyEntries= ImportStart(path); }
136 catch (Exception& e) {
138 throw e;
139 }
140 DidNotExistOrWasEmpty= (qtyEntries == 0);
141 return qtyEntries;
142 }
143
144 /// Closes and deletes the internal \p{iniFile} instance.
145 void ImportEnd() {
146 if(iniFile == nullptr) {
147 ALIB_ERROR( "VARIABLES", "No INI-file loaded when trying to end import/export." )
148 return;
149 }
150 delete iniFile;
151 iniFile= nullptr;
152 }
153
154 /// Closes and deletes the internal \p{iniFile} instance without writing an opened INI-file.
155 void ExportEnd() { ImportEnd(); }
156
157 /// Writes the contents of the internal \p{iniFile} instance created with #"ExportStart" into
158 /// an (optionally) different file and then deletes the instance.
159 /// @param path The file path for writing.
160 void ExportEnd(const system::Path& path ) {
161 if(iniFile == nullptr) {
162 ALIB_ERROR( "VARIABLES", "No INI-file loaded when trying to import data." )
163 return;
164 }
165 iniFile->Write(path);
166 delete iniFile;
167 iniFile= nullptr;
168 }
169
170
171 /// Writes the given variable to the internal INI-file.
172 /// If an INI-file was previously loaded, only those variables which are not existing in the
173 /// INI-file are written. This method can thus be used to "populate" an empty INI-file with
174 /// variables and their resourced or hard-coded default values and this way present all
175 /// configurable options to an end-user.
176 ///
177 /// Furthermore, a user can specify the word "writeback" (respectively what is resourced
178 /// with to token <c>"CFGIniWB"</c>) to force overwriting the INI-file contents with the current
179 /// value of the variable.
180 ///
181 /// @param var The variable to export.
182 /// @return \c true if the variable either did not exist yet in the INI-file or if it existed
183 /// and the write-back mechanism was in place. \c false otherwise.
185 bool Export( const Variable& var );
186
187 /// Creates a variable cursor with the given \p{cfg} and \p{path} and passes it to overloaded
188 /// method #"Export(const" Variable&).
189 /// @param path The path of the variable to export.
190 /// @return \c true if the variable either did not exist yet in the INI-file or if it existed
191 /// and the write-back mechanism was in place. \c false otherwise.
192 bool Export(const String& path) {
193 auto cursor= configuration.Root();
194 auto remainder= cursor.GoTo(path);
195 if( remainder.IsNotEmpty() ) {
196 ALIB_WARNING("VARIABLES", "Configuration variable path \"{}\" to export not found.",
197 path)
198 return false;
199 }
200 return Export( Variable(cursor) );
201 }
202
203
204 /// Writes all variables below the given #"StringTree::Cursor;*"
205 /// of the #"Configuration" into the #"iniFile", previously created with #"ExportStart".
206 /// If an INI-file was previously loaded, only those variables which are not existing in the
207 /// INI-file are written.
208 /// This method can thus be used to "populate" an empty INI-file with default values and
209 /// this way present all configurable options to an end-user.
210 ///
211 /// Furthermore, a user can specify the word "writeback" (respectively what is resourced
212 /// with to token <c>"CFGIniWB"</c>) to force overwriting the INI-file contents with the current
213 /// value of the variable.
214 ///
215 /// @param cursor A cursor into the configuration's #"StringTree".
216 /// @param directChildrenOnly If \c true, only the direct children of this cursor are written
217 /// as variables. Defaults to \c false.
218 /// @return The number of variables exported. A negative value on error.
220 int ExportSubTree( Configuration::Cursor cursor, bool directChildrenOnly= false );
221
222 /// Invokes #ExportSubTree(Configuration::Cursor, bool) by creating a cursor from the given
223 /// \p{path}
224 /// @param path The path to the subtree (or single variable) to use.
225 /// @param directChildrenOnly If \c true, only the direct children of this \p{path} are written
226 /// as variables. Defaults to \c false.
227 /// @return The number of variables exported. A negative value on error.
228 int ExportSubTree( const String& path, bool directChildrenOnly= false ) {
229 auto cursor= configuration.Root();
230 auto remainder= cursor.GoTo(path);
231 if( remainder.IsNotEmpty() ) {
232 return -1;
233 }
234
235 return ExportSubTree( cursor, directChildrenOnly );
236 }
237
238 /// Searches the entry of the internal INI-file that represents the given \p{variable}
239 /// @param variable The variable to search in the INI-file.
240 /// @return The section and entry if found. If not found, the second member of the pair is
241 /// emtpy.
243 IniFile::Handle SearchEntry ( const Variable& variable );
244
245 /// Searches the entry of the internal INI-file that represents the given variable determined
246 /// by parameter \p{path}
247 /// @param path The path of the variable to search in the INI-file.
248 /// @return The section and entry if found. If not found, the second member of the pair is
249 /// emtpy.
251 IniFile::Handle SearchEntry ( const String& path );
252
253 /// This method may be used to set the #"config_IniFile_writebackflag;writeback flag"
254 /// of an entry in the associated INI-file. The flag is only set if the entry was
255 /// programmatically created (usually with one of the <b>Export</b>-methods of this class) and
256 /// if it was not present in the INI-file before.
257 /// @see Chapter #"alib_variables_external_session" of the Programmer's Manual of module
258 /// \alib_variables_nl.
259 /// @param path The path of the variable to export.
260 /// @return \c true if the variable did exist and was newly added to the INI-file, \c false
261 /// otherwise.
263 bool SetWriteBackFlag( const String& path );
264
265 /// Invokes overloaded method #SetWriteBackFlag(const String& path).
266 /// @param var The variable to modifiy.
267 /// @return \c true if the variable did exist and was newly added to the INI-file, \c false
268 /// otherwise.
270 bool SetWriteBackFlag( const Variable& var );
271
272 #if ALIB_RESOURCES
273 /// This is a utility function that reads section comments from
274 /// #"alib_mod_resources;externalized string resources".
275 ///
276 /// All sections of the underlying INI-file are processed, but resourced comments
277 /// are only added in the case that a section's comment string is \c nulled. This is not the
278 /// case if a section was read from an INI-file, as even if no comments were given,
279 /// the field is empty but not \e nulled. In other words, only sections that have been
280 /// programmatically added during the run of software are changed<br>
281 /// This approach allows a user to remove the comments, without the software restoring them.
282 ///
283 /// The resource names are assembled from given \p{resourceNamePrefix} and the section name.
284 /// The resource strings found are processed using the method
285 /// #"Paragraphs.AddMarked(const BoxedObjects&)".
286 /// This allows using text macros like <b>'\@HL'</b> to format the text.
287 ///
288 /// \see
289 /// Field #LineWidth, which is respected when formatting comment lines.
290 ///
291 /// @param resourcePool The resource pool to use.
292 /// @param resourceCategory The category of the resourced comments.
293 /// @param resourceNamePrefix A prefix of the resource name.
294 /// @return The number of section comments written.
295 /// This is useful to detect if the INI-file needs to be written.
297 int AddResourcedSectionComments( ResourcePool& resourcePool,
298 const NString& resourceCategory,
299 const NString& resourceNamePrefix );
300
301 /// This is a shortcut to the overloaded method, accepting a #"ResourceHolder"
302 /// instead of parameters \p{resourcePool} and \p{resourceCategory}.
303 /// @param resourceHolder A container holding a resource pool and a fixed category.
304 /// @param resourceNamePrefix A prefix of the resource name.
305 /// @return The number of section comments written.
306 /// This is useful to detect if the INI-file needs to be written.
308 const NString& resourceNamePrefix ) {
309 return AddResourcedSectionComments( resourceHolder.GetResourcePool(),
310 resourceHolder.ResourceCategory,
311 resourceNamePrefix );
312 }
313 #endif
314
315 /// Allows access to the internal INI-file object created with either method #ImportStart or
316 /// #ExportStart. In debug-compilations, this method asserts that an INI-file was opened.
317 /// In release-compilations, a non-existing INI-file leads to undefined behavior.
318 /// @return The currently opened INI-File.
320 ALIB_ASSERT_ERROR( iniFile != nullptr, "VARIABLES",
321 "No INI-file loaded when trying to access it." )
322 return *iniFile;
323 }
324
325}; // class IniFileFeeder
326
327
328} // namespace alib[::config]
329
330/// Type alias in namespace \b alib.
332
333} // namespace [alib]
#define ALIB_DLL
Definition alib.inl:573
#define A_CHAR(STR)
Definition alib.inl:1325
#define ALIB_WARNING(domain,...)
Definition alib.inl:1141
#define ALIB_ASSERT_WARNING(cond, domain,...)
Definition alib.inl:1145
#define ALIB_ERROR(domain,...)
Definition alib.inl:1140
#define ALIB_EXPORT
Definition alib.inl:562
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1144
const Enum & Type() const
void ExportEnd()
Closes and deletes the internal iniFile instance without writing an opened INI-file.
int AddResourcedSectionComments(ResourcePool &resourcePool, const NString &resourceCategory, const NString &resourceNamePrefix)
int ExportSubTree(Configuration::Cursor cursor, bool directChildrenOnly=false)
int ImportStart(const system::Path &path)
IniFile * iniFile
The INI-file. Created with methods #"ImportStart" and #"ExportStart".
void ExportEnd(const system::Path &path)
bool Export(const String &path)
bool SetWriteBackFlag(const String &path)
Configuration & configuration
The configuration to work with. Set with construction.
int ImportSection(const String &sectionName)
void ImportEnd()
Closes and deletes the internal iniFile instance.
int importSection(IniFile::Section &section)
Priority priority
The priority to use to define variables. Set with construction.
int ExportStart(const system::Path &path)
int AddResourcedSectionComments(resources::ResourceHolder &resourceHolder, const NString &resourceNamePrefix)
bool Export(const Variable &var)
int ExportSubTree(const String &path, bool directChildrenOnly=false)
IniFile::Handle SearchEntry(const Variable &variable)
IniFileFeeder(Configuration &pConfiguration, Priority pPriority=Priority::ConfigFile)
@ ErrorOpeningFile
File not found when reading.
Definition inifile.inl:382
strings::TString< nchar > NString
Type alias in namespace alib.
Definition string.inl:2181
resources::ResourcePool ResourcePool
Type alias in namespace alib.
variables::Variable Variable
Type alias in namespace alib.
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2172
exceptions::Exception Exception
Type alias in namespace alib.
variables::IniFileFeeder IniFileFeeder
Type alias in namespace alib.
A pair of pointers to a section and an entry in the section.
Definition inifile.inl:162
A section of the INI-file.
Definition inifile.inl:145