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