ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
plugins.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2024 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
8
9#if !defined(ALIB_DOX)
10# if !defined (HPP_ALIB_CONFIG_PLUGINS)
12# endif
13
14# if !defined (HPP_ALIB_CAMP_ENVIRONMENT)
16# endif
17# if !defined (HPP_ALIB_CONFIG_CONFIG)
18# include "alib/config/config.hpp"
19# endif
20
21# if !defined (HPP_ALIB_LANG_CAMP_INLINES)
23# endif
24
25#endif // !defined(ALIB_DOX)
26
27namespace alib { namespace config {
28
29// #################################################################################################
30// XTernalizer
31// #################################################################################################
33{
34 Substring parser(src);
35 parser.Trim();
36 if( parser.CharAtStart() == '"' && parser.CharAtEnd() == '"')
37 {
38 parser.ConsumeChar <false>();
39 parser.ConsumeCharFromEnd<false>();
40 }
41 bool lastWasSlash= false;
42
43 while( parser.IsNotEmpty() )
44 {
45 character c= parser.ConsumeChar<false>();
46
47 if( lastWasSlash )
48 {
49 lastWasSlash= false;
50 character escChr= c == '\\' ? '\\' :
51 c == '"' ? '"' :
52 c == 'n' ? '\n' :
53 c == 'r' ? '\r' :
54 c == 't' ? '\t' :
55 c == 'a' ? '\a' :
56 c == 'b' ? '\b' :
57 c == 'v' ? '\v' :
58 c == 'f' ? '\f' :
59 c == 'e' ? '\033' :
60 c;
61
62 dest._<false>(escChr);
63 continue;
64 }
65
66 if( c== '\\' )
67 {
68 lastWasSlash= true;
69 continue;
70 }
71
72 dest._<false>(c);
73 }
74}
75
76void XTernalizer::ExternalizeValue( const String& src, AString& dest, character delim )
77{
78 Substring parser(src);
79 bool needsQuotes= parser.CharAtStart() == ' '
80 || parser.CharAtStart() == '\t'
81 || parser.CharAtEnd() == ' '
82 || parser.CharAtEnd() == '\t'
83 || parser.IndexOf( delim ) >= 0;
84 if ( needsQuotes )
85 dest._<false>('"');
86
87 while( parser.IsNotEmpty() )
88 {
89 character c= parser.ConsumeChar();
90
91 switch(c)
92 {
93 case '"' : dest._<false>(needsQuotes ? "\\\"" : "\"");
94 break;
95 case '\\' : dest._<false>("\\\\"); break;
96 case '\r' : dest._<false>("\\r" ); break;
97 case '\n' : dest._<false>("\\n" ); break;
98 case '\t' : dest._<false>("\\t" ); break;
99 case '\a' : dest._<false>("\\a" ); break;
100 case '\b' : dest._<false>("\\b" ); break;
101 case '\v' : dest._<false>("\\v" ); break;
102 case '\f' : dest._<false>("\\f" ); break;
103 case '\033' : dest._<false>("\\e" ); break;
104 default : dest._<false>(c); break;
105 }
106 }
107
108 if ( needsQuotes )
109 dest._('"');
110}
111
112void XTernalizer::LoadFromString( Variable& variable, const String& value )
113{
114 variable.ClearValues();
116 Substring src( value );
117
118 if( variable.Delim() == '\0' )
119 {
120 InternalizeValue( src, tempBuf );
121 variable.Add( tempBuf );
122 return;
123 }
124
125 // tokenize
126 bool inQuote= false;
127 bool lastWasSlash= false;
128 integer idx= 0;
129 while( idx < src.Length() )
130 {
131 character c= src.CharAt<false>( idx++ );
132
133 if( lastWasSlash )
134 {
135 lastWasSlash= false;
136 continue;
137 }
138
139 if( c== '\\' )
140 {
141 lastWasSlash= true;
142 continue;
143 }
144
145 if( c== '"' )
146 {
147 inQuote= !inQuote;
148 continue;
149 }
150
151 if( !inQuote && c == variable.Delim() )
152 {
153 Substring tok= src.Substring<false>( 0, idx - 1 );
154 InternalizeValue( tok, tempBuf );
155 variable.Add(tempBuf);
156 tempBuf.Reset();
157 src.ConsumeChars( idx );
158 src.TrimStart();
159 idx= 0;
160 }
161 }
162
163 if ( src.IsNotEmpty() )
164 {
165 InternalizeValue( src, tempBuf );
166 variable.Add( tempBuf );
167 }
168}
169
170// #################################################################################################
171// CLIArgs
172// #################################################################################################
174{
175 return CONFIG.GetResource( "CfgPlgCLI" );
176}
177
178bool CLIArgs::Load( Variable& variable, bool searchOnly )
179{
180 // check if category may me left out
181 bool allowWithoutCategory= false;
182 for (auto& defaultCategory : DefaultCategories )
183 if( (allowWithoutCategory= variable.Category().Equals<false>( defaultCategory )) == true )
184 break;
185
186 String256 stringConverter;
187 stringConverter.DbgDisableBufferReplacementWarning();
188
189
190 std::vector<AString>::iterator argsIt;
191 if( !AlternativeArgs.empty() )
192 {
194 argsIt = AlternativeArgs.begin();
195 }
196
197
198 for ( size_t i= !AlternativeArgs.empty() ? 0 : 1 ; i < argCount ; ++i )
199 {
200 // create sub-string on actual variable (trim if somebody would work with quotation marks...)
201 Substring cliArg;
202
203 if( !AlternativeArgs.empty() )
204 {
205 cliArg= *argsIt;
206 ++argsIt;
207 }
208 else
209 {
211 if (!wArgs)
212 {
213 if(!std::is_same<character, char>::value)
214 {
215 stringConverter.Reset( reinterpret_cast<const char**>(argVector)[i] );
216 cliArg= stringConverter;
217 }
218 else
219 cliArg= reinterpret_cast<const character**>(argVector)[i];
220 }
221 else
222 {
223 if(!std::is_same<character, wchar_t>::value)
224 {
225 stringConverter.Reset( reinterpret_cast<const wchar_t**>(argVector)[i] );
226 cliArg= stringConverter;
227 }
228 else
229 cliArg= reinterpret_cast<const character**>(argVector)[i];
230 }
232 }
233
234 cliArg.Trim();
235
236 // request '-' and allow a second '-'
237 if ( !cliArg.ConsumeChar('-') )
238 continue;
239 cliArg.ConsumeChar('-');
240
241 // try names
242
243 if ( ! cliArg.ConsumeString<lang::Case::Ignore>( variable.Fullname() )
244 && !( allowWithoutCategory && cliArg.ConsumeString<lang::Case::Ignore>( variable.Name() ) )
245 && !( AllowedMinimumShortCut > 0
246 && ( cliArg.ConsumePartOf( variable.Fullname(), AllowedMinimumShortCut + 1 + static_cast<int>(variable.Category().Length()) )
247 ||( allowWithoutCategory && cliArg.ConsumePartOf( variable.Name() , AllowedMinimumShortCut ) )
248 )
249 )
250 )
251 continue; // next arg
252
253 // found --CAT_NAME. If rest is empty or continues with '=', we set
254 if ( cliArg.IsEmpty() )
255 {
256 if ( !searchOnly )
257 variable.Add(A_CHAR(""));
258 return true;
259 }
260
261 if ( cliArg.ConsumeChar<true, lang::Whitespaces::Trim>() == '=' )
262 {
263 if ( !searchOnly )
264 StringConverter->LoadFromString( variable, cliArg.Trim() );
265 return true;
266 }
267 }
268
269 return false;
270}
271
272// #################################################################################################
273// CLIArgs Iterator
274// #################################################################################################
275//! @cond NO_DOX
276namespace {
277
278class CLIArgsIteratorImpl : public ConfigurationPlugin::Iterator
279{
280 CLIArgs& parent;
281 String sectionName;
282 size_t nextArgNo;
283
284
285 public:
286
287 CLIArgsIteratorImpl( CLIArgs& cliArgs, const String& pSectionName )
288 : parent(cliArgs)
289 , sectionName(pSectionName)
290 , nextArgNo(0)
291 {
292
293 }
294
295 virtual ~CLIArgsIteratorImpl() override
296 {}
297
298 virtual bool Next( Variable& variable ) override
299 {
300 return detail::nextCLIArg( parent, nextArgNo, sectionName, variable );
301 }
302};
303
304} // anonymous namespace
305
306namespace detail {
307
308bool nextCLIArg( CLIArgs& cliArgs, size_t& nextArgNo, const String& sectionName, Variable& variable )
309{
310 variable.Reset(lang::CurrentData::Clear);
311
312 size_t qtyArgs= cliArgs.argCount;
313 std::vector<AString>::iterator argsIt;
314 if( !cliArgs.AlternativeArgs.empty() )
315 {
316 qtyArgs= cliArgs.AlternativeArgs.size();
317 argsIt= cliArgs.AlternativeArgs.begin();
318 }
319
320 if( nextArgNo >= qtyArgs )
321 return false;
322
323 // check if category may have been left out
324 bool allowWithoutCategory= false;
325 for (auto& defaultCategory : cliArgs.DefaultCategories )
326 if( (allowWithoutCategory= sectionName.Equals( defaultCategory )) == true )
327 break;
328
329 String256 stringConverter;
330 stringConverter.DbgDisableBufferReplacementWarning();
331
332 // skip index 0 (command name) if not special args string vector set.
333 if( nextArgNo == 0 && cliArgs.AlternativeArgs.empty() )
334 nextArgNo= 1;
335 while( nextArgNo < qtyArgs )
336 {
337 // create sub-string on actual variable (trim if somebody would work with quotation marks...)
338 Substring cliArg;
339 if( !cliArgs.AlternativeArgs.empty() )
340 {
341 cliArg= *argsIt;
342 ++argsIt;
343 }
344 else
345 {
347 if (!cliArgs.wArgs)
348 {
349 if(!std::is_same<character, char>::value)
350 {
351 stringConverter.Reset( reinterpret_cast<const char**>(cliArgs.argVector)[nextArgNo] );
352 cliArg= stringConverter;
353 }
354 else
355 cliArg= reinterpret_cast<const character**>(cliArgs.argVector)[nextArgNo];
356 }
357 else
358 {
359 if(!std::is_same<character, wchar_t>::value)
360 {
361 stringConverter.Reset( reinterpret_cast<const wchar_t**>(cliArgs.argVector)[nextArgNo] );
362 cliArg= stringConverter;
363 }
364 else
365 cliArg= reinterpret_cast<const character**>(cliArgs.argVector)[nextArgNo];
366 }
368 }
369 cliArg.Trim();
370 ++nextArgNo;
371
372 // request '-' and allow a second '-'
373 if ( !cliArg.ConsumeChar('-') )
374 continue;
375 cliArg.ConsumeChar('-');
376
377 // consume category
378 if( !allowWithoutCategory && !sectionName.IsEmpty()
379 && ( !cliArg.ConsumeString<lang::Case::Ignore>( sectionName )
380 || !cliArg.ConsumeChar('_' ) ) )
381 continue;
382
383 // check for '=' sign
384 integer equalSignPos= cliArg.IndexOf( '=' );
385 if( equalSignPos < 0 )
386 continue;
387
388 // found!
389 Substring value;
390 cliArg .Split ( equalSignPos, value, 1);
391 variable.Declare( sectionName, cliArg );
392 cliArgs.StringConverter->LoadFromString( variable, value.Trim() );
393 return true;
394 }
395
396 // not found
397 return false;
398}
399} //namespace detail
400
401ConfigurationPlugin::Iterator* CLIArgs::GetIterator( const String& sectionName )
402{
403 return new CLIArgsIteratorImpl( *this, sectionName );
404}
405
406//! @endcond
407
408// #################################################################################################
409// Environment
410// #################################################################################################
415
417{
418 return CONFIG.GetResource( "CfgPlgEnv" );
419}
420
421bool Environment::Load( Variable& variable, bool searchOnly )
422{
424 String256 nameZeroTerminated; nameZeroTerminated.DbgDisableBufferReplacementWarning();
425 nameZeroTerminated << variable.Fullname();
426 EnvironmentVariables::Get( nameZeroTerminated, value, lang::CurrentData::Keep );
427 if ( value.IsEmpty() )
428 return false;
429
430 if( !searchOnly )
431 StringConverter->LoadFromString( variable, value );
432 return true;
433}
434
435}} // namespace [alib::config]
size_t argCount
The number of command line arguments.
virtual ALIB_API bool Load(Variable &variable, bool searchOnly=false) override
Definition plugins.cpp:178
const void ** argVector
The list of command line arguments.
virtual ALIB_API Iterator * GetIterator(const String &sectionName) override
virtual ALIB_API String Name() const override
Definition plugins.cpp:173
std::vector< AString > AlternativeArgs
std::vector< AString > DefaultCategories
virtual ALIB_API bool Load(Variable &variable, bool searchOnly=false) override
Definition plugins.cpp:421
virtual ALIB_API String Name() const override
Definition plugins.cpp:416
ALIB_API const String & Fullname()
Definition variable.cpp:266
ALIB_API void Add(const String &value)
Definition variable.cpp:223
character Delim() const
Definition variable.hpp:506
const String & Name() const
Definition variable.hpp:496
const String & Category() const
Definition variable.hpp:487
Variable & ClearValues(int startIdx=0)
Definition variable.hpp:721
virtual ALIB_API void ExternalizeValue(const String &src, AString &dest, character delim)
Definition plugins.cpp:76
virtual ALIB_API void InternalizeValue(const String &src, AString &dest)
Definition plugins.cpp:32
virtual ALIB_API void LoadFromString(Variable &variable, const String &src)
Definition plugins.cpp:112
const String & GetResource(const NString &name)
TAString & _(const TString< TChar > &src, integer regionStart, integer regionLength=MAX_LEN)
Definition astring.hpp:1056
void DbgDisableBufferReplacementWarning()
Definition astring.hpp:353
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.hpp:889
constexpr bool IsEmpty() const
Definition string.hpp:414
TChar CharAt(integer idx) const
Definition string.hpp:437
constexpr bool IsNotEmpty() const
Definition string.hpp:420
constexpr integer Length() const
Definition string.hpp:357
TChar CharAtStart() const
Definition string.hpp:459
TString< TChar > Substring(integer regionStart, integer regionLength=MAX_LEN) const
Definition string.hpp:314
bool Equals(const TString< TChar > &rhs) const
Definition string.hpp:573
TChar CharAtEnd() const
Definition string.hpp:481
TSubstring & Trim(const TCString< TChar > &whiteSpaces=TT_StringConstants< TChar >::DefaultWhitespaces())
bool ConsumeString(const TString< TChar > &consumable)
TSubstring & Split(integer position, TSubstring &target, integer separatorWidth=0, bool trim=false)
integer ConsumePartOf(const TString< TChar > &consumable, int minChars=1)
integer ConsumeChars(integer regionLength, TSubstring *target=nullptr)
TSubstring & TrimStart(const TCString< TChar > &whiteSpaces=TT_StringConstants< TChar >::DefaultWhitespaces())
Definition substring.hpp:89
bool ConsumeCharFromEnd(TChar consumable)
#define A_CHAR(STR)
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:715
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
Definition alib.hpp:644
bool nextCLIArg(CLIArgs &cliArgs, size_t &nextArgNo, const String &sectionName, Variable &variable)
@ Equals
Verbal alias "Equals" to operator '=='.
@ Trim
Trim whitespaces away.
@ Keep
Chooses not no clear existing data.
@ Clear
Chooses to clear existing data.
Definition alib.cpp:57
config::Variable Variable
Type alias in namespace alib.
Definition variable.hpp:839
strings::TSubstring< character > Substring
Type alias in namespace alib.
LocalString< 256 > String256
Type alias name for TLocalString<character,256> .
characters::character character
Type alias in namespace alib.
strings::TString< character > String
Type alias in namespace alib.
config::Config CONFIG
Definition config.cpp:40
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:286
static ALIB_API bool Get(const CString &varName, AString &target, lang::CurrentData targetData=lang::CurrentData::Clear)