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