ALib C++ Library
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
inifilefeeder.cpp
1//##################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2025 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6//##################################################################################################
7#include "alib_precompile.hpp"
8#if !defined(ALIB_C20_MODULES) || ((ALIB_C20_MODULES != 0) && (ALIB_C20_MODULES != 1))
9# error "Symbol ALIB_C20_MODULES has to be given to the compiler as either 0 or 1"
10#endif
11#if ALIB_C20_MODULES
12 module;
13#endif
14//========================================= Global Fragment ========================================
16#include <fstream>
17//============================================== Module ============================================
18#if ALIB_C20_MODULES
19 module ALib.Variables.IniFile;
20 import ALib.Strings.StdIOStream;
21# if ALIB_EXCEPTIONS
22 import ALib.Exceptions;
23# endif
24 import ALib.System;
25 import ALib.Variables;
26# if ALIB_FORMAT
27 import ALib.Format;
28 import ALib.Format.Paragraphs;
29# endif
30#else
32# include "ALib.Exceptions.H"
35# include "ALib.System.H"
36# include "ALib.Variables.H"
37# include "ALib.Format.H"
40#endif
41//========================================== Implementation ========================================
42
43namespace alib::variables {
44
45//##################################################################################################
46// helpers
47//##################################################################################################
48std::pair<IniFile::Section*, IniFile::Entry*> IniFileFeeder::SearchEntry ( const String& path ) {
49 if(iniFile == nullptr) {
50 ALIB_ERROR( "VARIABLES", "No INI-file loaded when trying to search data." )
51 return std::pair<IniFile::Section*, IniFile::Entry*>(nullptr, nullptr);
52 }
53
54 // separate section/entry name
55 auto sectionSeparator= path.LastIndexOf( configuration.Separator() );
56 String sectionName= (sectionSeparator != -1) ? path.Substring<NC>(0, sectionSeparator ) : EMPTY_STRING;
57 String entryName = (sectionSeparator != -1) ? path.Substring<NC>(sectionSeparator + 1, path.Length() - sectionSeparator - 1) : path;
58
59 // search for existing entry
60 return iniFile->SearchEntry(sectionName, entryName);
61}
62
63std::pair<IniFile::Section*, IniFile::Entry*> IniFileFeeder::SearchEntry ( const Variable& var ) {
64 ALIB_ASSERT_ERROR( var.IsDeclared(), "VARIABLES", "Given Variable not declared." )
65 ALIB_ASSERT_ERROR( &var.GetConfiguration() == &configuration, "VARIABLES",
66 "Variable belongs to different configuration: ", var )
67 return SearchEntry( String256( var ) );
68}
69
70//##################################################################################################
71// Import interface
72//##################################################################################################
73int IniFileFeeder::ImportSection( const String& sectionName, const String& typeName ) {
74 if(iniFile == nullptr) {
75 ALIB_ERROR( "VARIABLES", "No INI-file loaded when trying to import data." )
76 return 0;
77 }
78
79 auto* section= iniFile->SearchSection( sectionName );
80 if(section == nullptr) {
81 ALIB_WARNING( "VARIABLES", "Section named \"{}\" not found in INI-file.", sectionName )
82 return 0;
83 }
84
85 int cnt= 0;
86 String256 varName;
87
88 varName.Reset(sectionName);
89 if( varName.IsNotEmpty())
90 varName << configuration.Separator();
91
92 // loop over all entries
93 for ( auto& entry : section->Entries ) {
94 StringLengthResetter sectionNameResetter(varName);
95 varName << entry.Name;
96 Variable var(configuration, varName, typeName);
97 if( var.Define( priority) ) {
98 var.Import(entry.Value, priority, &configuration.Escaper );
99 ++cnt;
100 } }
101
102 return cnt;
103}
104
106 int cnt= 0;
107 String256 varName;
108
109 varName.Reset(section.Name);
110 if( varName.IsNotEmpty())
111 varName << configuration.Separator();
112
113 // loop over all entries
114 for ( auto& entry : section.Entries ) {
115 // Try if variable is declared and has lower or equal priority than us.
116 StringLengthResetter sectionNameResetter(varName);
117 varName << entry.Name;
119 Substring value= entry.Value;
120 if( var.Try(varName) ) {
121 var.Import(value, priority, &configuration.Escaper );
122 ++cnt;
123 continue;
124 }
125
126 // Variable not declared. Copy value to undeclared input variables
127 configuration.PresetImportString(varName, value, &configuration.Escaper, priority);
128 }
129
130 return cnt;
131}
132
133int IniFileFeeder::ImportSection( const String& sectionName ) {
134 if(iniFile == nullptr) {
135 ALIB_ERROR( "VARIABLES", "No INI-file loaded when trying to import data." )
136 return 0;
137 }
138
139 auto* section= iniFile->SearchSection( sectionName );
140 if(section == nullptr) {
141 ALIB_WARNING( "VARIABLES", "Section name \"{}\" not found in INI-file.", sectionName )
142 return 0;
143 }
144
145 return importSection(*section);
146}
147
149 if(iniFile == nullptr) {
150 ALIB_ERROR( "VARIABLES", "No INI-file loaded when trying to import data." )
151 return 0;
152 }
153
154 int cnt= 0;
155 String256 varName;
156
157 // loop over all sections
158 for ( IniFile::Section& section : iniFile->Sections )
159 cnt+= importSection( section );
160
161 return cnt;
162}
163
164//##################################################################################################
165// Export interface
166//##################################################################################################
168 if(iniFile == nullptr) {
169 ALIB_ERROR( "VARIABLES", "No INI-file loaded when trying to export data." )
170 return false;
171 }
172 ALIB_ASSERT_ERROR(var.IsDeclared(), "VARIABLES", "Variable to export not declared: ", var)
173
174 String256 name(var);
175
176 // separate section/entry name
177 auto sectionSeparator= name.LastIndexOf( var.GetConfiguration().Separator() );
178 String sectionName= (sectionSeparator != -1) ? name.Substring<NC>(0, sectionSeparator ) : EMPTY_STRING;
179 String entryName = (sectionSeparator != -1) ? name.Substring<NC>(sectionSeparator + 1, name.Length() - sectionSeparator - 1) : name;
180
181 // search for existing entry
182 auto pair= iniFile->SearchEntry(sectionName, entryName);
183 auto* entry= pair.second;
184 if( entry ) {
185 // exists and no write back?
186 if( !entry->WriteBack && !pair.first->WriteBack )
187 return false;
188 } else {
189 // create entry
190 auto sectionIt= iniFile->SearchOrCreateSection( sectionName );
191 entry = iniFile->CreateEntry( sectionIt.first, entryName );
192 }
193
194 {String4K buf;
196 var.Export( buf, &configuration.Escaper );
197 entry->NewValue.Allocate(iniFile->Allocator, buf );
198 }
199
200 // add comments
201 if(entry->Comments.IsNull()) {
202 auto* decl= var.GetDeclaration();
203 if( decl && decl->Comments().IsNotEmpty() )
204 iniFile->AddComments( entry->Comments, decl->Comments(), DefaultCommentPrefix );
205 }
206
207 return true;
208}
209
210int IniFileFeeder::ExportSubTree( Configuration::Cursor cursor, bool directChildrenOnly ) {
211 if(iniFile == nullptr) {
212 ALIB_ERROR( "VARIABLES", "No INI-file loaded when trying to export data." )
213 return 0;
214 }
215 int cnt= 0;
216 // check cursor itself first
217 if( !cursor.IsRoot() ) {
218 Variable var(cursor);
219 if( var.IsDeclared() )
220 if( Export( var ) )
221 cnt++;
222 }
223
226 stit.SetMaxDepth( directChildrenOnly ? 0 : (std::numeric_limits<unsigned>::max)() );
227 stit.Initialize( cursor, lang::Inclusion::Exclude );
228 while ( stit.IsValid() ) {
229 if( stit.Node().Name().Equals(A_CHAR("$PRESETS")) ) {
230 stit.NextSibling();
231 continue;
232 }
233
234 Variable var(stit.Node());
235 if( var.IsDeclared() && var.IsDefined() ) {
236 if( Export( var ) )
237 cnt++;
238 }
239 stit.Next();
240 }
241 return cnt;
242}
243
244#if ALIB_RESOURCES
246 const NString& resourceCategory,
247 const NString& resourceNamePrefix ) {
248 if(iniFile == nullptr) {
249 ALIB_ERROR( "VARIABLES", "No INI-file loaded when trying to import data." )
250 return 0;
251 }
252
253 // add section comments from resources to INI-file
254 int cnt= 0;
255 for( auto& section : iniFile->Sections )
256 if( section.Comments.IsNull() ) {
257 auto& comment= resourcePool.Get( resourceCategory,
258 NString128() << resourceNamePrefix << section.Name
259 ALIB_DBG(, false));
260 if( comment.IsNull() )
261 continue;
262
263 ++cnt;
264 Paragraphs text;
266 text.LineWidth= LineWidth;
267 text.Buffer._(NEW_LINE);
268 text.AddMarked( comment );
269 }
270 section.Comments.Allocate(iniFile->Allocator, text.Buffer);
271 }
272 return cnt;
273}
274#endif
275
277 auto entry= SearchEntry( path );
278 ALIB_ASSERT_WARNING( entry.second , "VARIABLES",
279 "Variable \"{}\" to be marked as 'writeback' not found.", path )
280
281 if( entry.second && entry.second->RawValue.IsEmpty() ) {
282 entry.second->WriteBack= true;
283 return true;
284 }
285 return false;
286}
287
289 ALIB_ASSERT_ERROR( var.IsDeclared(), "VARIABLES", "Given Variable not declared." )
290 ALIB_ASSERT_ERROR( &var.GetConfiguration() == &configuration, "VARIABLES",
291 "Variable belongs to different configuration: ", var)
292 return SetWriteBackFlag( String256(var) );
293}
294
295
296} // namespace [alib::variables]
void SetMaxDepth(unsigned int newMaxDepth=(std::numeric_limits< unsigned >::max)())
void Initialize(CursorType startNode, lang::Inclusion includeStartNode)
void SetPathGeneration(lang::Switch pathGeneration)
constexpr CharacterType Separator() const noexcept
static ALIB_DLL threads::RecursiveLock DefaultLock
void AddMarked(boxing::TBoxes< TAllocatorArgs > &args)
integer LineWidth
Used as parameter lineWidth of static method invocations.
virtual const String & Get(const NString &category, const NString &name, bool dbgAssert)=0
TAString & _(const TAppendable &src)
void DbgDisableBufferReplacementWarning()
Definition tastring.inl:244
constexpr integer Length() const
Definition string.inl:316
constexpr bool IsNotEmpty() const
Definition string.inl:369
integer LastIndexOf(TChar needle, integer startIndex=MAX_LEN) const
Definition string.inl:925
void Allocate(TAllocator &allocator, const TString< TChar > &copy)
Definition string.inl:1745
TString< TChar > Substring(integer regionStart, integer regionLength=MAX_LEN) const
Definition string.inl:384
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.
ALIB_DLL bool SetWriteBackFlag(const String &path)
Configuration & configuration
The configuration to work with. Set with construction.
ALIB_DLL int ImportSection(const String &sectionName)
ALIB_DLL int importSection(IniFile::Section &section)
Priority priority
The priority to use to define variables. Set with construction.
ALIB_DLL bool Export(const Variable &var)
ALIB_DLL bool Define(Priority requestedPriority=Priority::Standard)
Definition variable.cpp:261
ALIB_DLL void Import(const String &src, Priority priority, const StringEscaper *escaper=nullptr)
Definition variable.cpp:331
AString & Export(AString &dest, const StringEscaper *escaper=nullptr) const
bool Try(const String &name)
const Declaration * GetDeclaration() const
Configuration & GetConfiguration() const
#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_LOCK_RECURSIVE_WITH(lock)
Definition alib.inl:1340
#define ALIB_DBG(...)
Definition alib.inl:853
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1066
@ On
Switch it on, switched on, etc.
@ Exclude
Chooses exclusion.
strings::TStringLengthResetter< character,lang::HeapAllocator > StringLengthResetter
Type alias in namespace alib.
NLocalString< 128 > NString128
Type alias name for TLocalString<nchar,128>.
LocalString< 256 > String256
Type alias name for TLocalString<character,256>.
LocalString< 4096 > String4K
Type alias name for TLocalString<character,4096>.
constexpr CString NEW_LINE
A zero-terminated string containing the new-line character sequence.
Definition cstring.inl:616
constexpr const String EMPTY_STRING
An empty string of the default character type.
Definition string.inl:2251
strings::TString< nchar > NString
Type alias in namespace alib.
Definition string.inl:2198
format::Paragraphs Paragraphs
Type alias in namespace alib.
resources::ResourcePool ResourcePool
Type alias in namespace alib.
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2189
containers::StringTreeIterator< TTree > StringTreeIterator
Type alias in namespace alib.
strings::TSubstring< character > Substring
Type alias in namespace alib.
A section of the INI-file.
Definition inifile.inl:144
ListMA< Entry, Recycling::None > Entries
The list of variables of the section.
Definition inifile.inl:156
String Name
The name of the section.
Definition inifile.inl:154