ALib C++ Library
Library Version: 2412 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
arguments.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 !DOXYGEN
10# include "alib/cli/arguments.hpp"
15#endif // !DOXYGEN
16
17
18// ##########################################################################################
19// ### Tuple loaders
20// ##########################################################################################
21
22namespace alib { namespace cli {
23
24// ##########################################################################################
25// ### Methods of Command, Option, etc.
26// ##########################################################################################
27
29{
30 Tokenizer tknzr( record.parameters , '/' );
31 while( tknzr.Next().IsNotEmpty() )
32 {
33ALIB_DBG( bool found= false; )
34
35 for( auto* paramDecl : CmdLine.ParameterDecls )
36 if( paramDecl->Name().StartsWith<CHK, lang::Case::Ignore>( tknzr.Actual ) )
37 {
38 Parameters.PushBack( paramDecl );
39 ALIB_DBG(found= true; )
40 break;
41 }
42
43 ALIB_ASSERT_ERROR( found, "CLI",
44 "Parameter named {!Q} not found while loading resources of command {!Q}.",
45 tknzr.Actual, Identifier() )
46 }
47}
48
50{
51 for( auto* param : Parameters )
52 if( param->Name().Equals<NC>( name ) )
53 return param;
54
55 return nullptr;
56}
57
58
59bool Option::Read( OptionDecl& decl, String& argProbablyReplaced, const integer argNo )
60{
61 String identifier = decl.Identifier();
62 character identifierC = decl.IdentifierChar();
63 auto argsExpected= decl.QtyExpectedArgsFollowing();
64 auto argsLeft = CmdLine->ArgsLeft.size() -1;
65
66 // read single/double hyphen options once
67 Substring arg= argProbablyReplaced;
68 Substring inArgArgument;
69 auto valueSeparator= arg.IndexOf<CHK, lang::Case::Sensitive>( decl.ValueSeparator() );
70 if( valueSeparator > 0 )
71 arg.Split<NC>( valueSeparator, inArgArgument, decl.ValueSeparator().Length() );
72
73 bool potentialIllegalContinuation= false;
74 if ( !( ( identifier.IsNotEmpty()
75 && arg.ConsumeString(A_CHAR("--"))
76 && arg.Length() >= decl.MinimumRecognitionLength()
77 && ( identifier.StartsWith<CHK, lang::Case::Ignore>( arg )
78 || true == (potentialIllegalContinuation= arg.StartsWith<CHK,lang::Case::Ignore>( identifier )) )
79
80 )
81
82 || ( arg.ConsumeChar('-')
83 && arg.ConsumeChar(identifierC) )
84 )
85 )
86 return false;
87
88 // Throw if the identifier was fully matched, but the argument continues with a
89 // non-alphanumerical value.
90 // (This is only allowed if separator was set in resource. But in this case, the flag will
91 // never match, because of the code above...)
92 if( potentialIllegalContinuation )
93 {
94 auto nextChar= arg.CharAt<NC>( identifier.Length() );
95 if( !isalnum( nextChar ) )
97 identifier, argNo, CmdLine->GetArg(argNo) );
98 return false;
99 }
100
101 Declaration= &decl;
102 Position= argNo;
103
105
106
107 // store in-arg argument
108 if( valueSeparator > 0)
109 {
110 Args.PushBack( inArgArgument );
111 if(argsExpected > 0 )
112 --argsExpected;
113 }
114
115
116 // error: not enough params
117 if ( argsExpected > integer(argsLeft) )
119 decl.Identifier(), argNo, CmdLine->GetArg(argNo),
120 argsExpected, argsLeft );
121
122 // store arg strings
123 for( integer i= 0; i < argsExpected; ++i )
124 Args.PushBack( CmdLine->GetArg(argNo + 1 + i) );
125 ConsumedArguments+= argsExpected;
126
127 return true;
128}
129
131{
132 auto& identifier= decl.Identifier();
133 String arg = CmdLine->PeekArg();
134
135 if ( arg.Length() < decl.MinimumRecognitionLength()
136 || !identifier.StartsWith<CHK,lang::Case::Ignore>( arg ) )
137 return false;
138
139 Declaration= &decl;
141 CmdLine->PopArg();
143
144 if( decl.Parameters.Count() == 0 )
145 return true;
146
147 auto paramDeclIt= decl.Parameters.begin();
148 while( paramDeclIt != decl.Parameters.end() )
149 {
150 Parameter param( CmdLine );
151 bool continueReading= param.Read( **paramDeclIt );
152 if( param.ConsumedArguments )
153 {
155 Parameter* paramFound= CmdLine->allocator().New<Parameter>(param);
156 if ( (*paramDeclIt)->IsOptional() )
157 ParametersOptional.PushBack( paramFound );
158 else
159 ParametersMandatory.PushBack( paramFound );
160
161 // start from the beginning
162 paramDeclIt= decl.Parameters.begin();
163 }
164 else
165 ++paramDeclIt;
166
167 // stop here if parameter read signaled this
168 if( !continueReading )
169 return false;
170 }
171
172 return true;
173}
174
176{
177 #if ALIB_DEBUG
178 bool found= false;
179 for( auto* paramDecl : Declaration->Parameters )
180 if( paramDecl->Name().Equals<NC>(name) )
181 {
182 found = true;
183 break;
184 }
185 ALIB_ASSERT_ERROR( found, "CLI", "Requested parameter {!Q} not defined.", name )
186 #endif
187
188 for( auto* param : ParametersMandatory )
189 if( param->Declaration->Name().Equals<NC>( name ) )
190 return param;
191
192 for( auto* param : ParametersOptional )
193 if( param->Declaration->Name().Equals<NC>( name ) )
194 return param;
195
196 return nullptr;
197}
198
200{
201 Parameter* param= GetParsedParameter( name );
202 return param && param->Args.IsNotEmpty() ? param->Args.Front()
203 : NULL_STRING;
204}
205
206
208{
209 Substring arg= CmdLine->PeekArg();
210 if( arg.IsNull() )
211 return false;
212
213 auto& identifier= decl.Identifier();
214 if ( identifier.IsEmpty() && decl.IsOptional() )
215 return false;
216
217 auto valueSeparator= arg.IndexOf<CHK, lang::Case::Sensitive>( decl.ValueSeparator() );
218 Substring inArgArgument;
219 if( valueSeparator > 0 )
220 arg.Split<NC>( valueSeparator, inArgArgument, decl.ValueSeparator().Length() );
221
222 if ( identifier.IsEmpty()
223 || ( arg.Length() >= decl.MinimumRecognitionLength()
224 && identifier.StartsWith<CHK,lang::Case::Ignore>( arg ) ) )
225 {
227 Declaration= &decl;
229 CmdLine->PopArg();
230 int argsExpected= decl.QtyExpectedArgsFollowing();
231
232 if( decl.Identifier().IsEmpty() )
233 {
234 Args.PushBack( arg );
235 }
236 else
237 {
238 if( inArgArgument.IsNotEmpty() )
239 {
240 Args.PushBack( inArgArgument );
241 --argsExpected;
242 }
243 }
244
245 // stop command?
246 if( argsExpected < 0 )
247 return false;
248
249 // error: not enough params
250 if ( argsExpected > static_cast<integer>(CmdLine->ArgsLeft.size()) )
253 argsExpected, CmdLine->ArgsLeft.size() );
254
255 // store arg strings
256 for( size_t i= 0; i < size_t( argsExpected ); ++i )
257 {
258 Args.PushBack( CmdLine->GetArg(*CmdLine->ArgsLeft.begin()) );
259 CmdLine->ArgsLeft.erase( CmdLine->ArgsLeft.begin() );
260 }
261 ConsumedArguments+= size_t( argsExpected );
262 }
263
264
265 return true;
266}
267
268void ERCommandDecl ::Parse()
269{
270 enums::EnumRecordParser::Get( ERSerializable::EnumElementName );
271 enums::EnumRecordParser::Get( ERSerializable::MinimumRecognitionLength );
272 enums::EnumRecordParser::Get( parameters , true );
273}
274
275void EROptionDecl ::Parse()
276{
277 enums::EnumRecordParser::Get( ERSerializable::EnumElementName );
278 enums::EnumRecordParser::Get( ERSerializable::MinimumRecognitionLength );
279 enums::EnumRecordParser::Get( identifierChar );
280 enums::EnumRecordParser::Get( valueSeparator );
281 enums::EnumRecordParser::Get( RequiredArguments );
282 enums::EnumRecordParser::Get( shortcutReplacementString , true );
283}
284
295
296void ERExitCodeDecl ::Parse()
297{
298 enums::EnumRecordParser::Get( ERSerializable::EnumElementName );
299 ERSerializable::MinimumRecognitionLength = 0;
300 enums::EnumRecordParser::Get( associatedCLIException , true );
301}
302
303}} // namespace alib::cli
ALIB_API void addParamDecls()
Definition arguments.cpp:28
ERCommandDecl record
A copy (!) of the enum record.
CommandLine & CmdLine
The command line instance we belong to.
const String & Identifier()
ALIB_API ParameterDecl * GetParameterDecl(const String &name)
Definition arguments.cpp:49
List< MonoAllocator, ParameterDecl * > Parameters
Command parameters.
List< MonoAllocator, ParameterDecl * > ParameterDecls
Possible Parameters.
virtual String GetArg(integer idx)
StdVectorMono< integer > ArgsLeft
MonoAllocator allocator
virtual String PeekArg()
virtual ALIB_API String PopArg()
const String & Identifier()
const String & ValueSeparator()
character IdentifierChar()
integer QtyExpectedArgsFollowing()
const String & Identifier()
const String & ValueSeparator()
const String & Name()
constexpr bool IsNull() const
Definition string.hpp:364
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.hpp:896
constexpr bool IsEmpty() const
Definition string.hpp:383
TChar CharAt(integer idx) const
Definition string.hpp:444
constexpr bool IsNotEmpty() const
Definition string.hpp:389
constexpr integer Length() const
Definition string.hpp:326
bool StartsWith(const TString &needle) const
Definition string.hpp:820
bool ConsumeString(const TString< TChar > &consumable)
TSubstring & Split(integer position, TSubstring &target, integer separatorWidth=0, bool trim=false)
ALIB_API TSubstring< TChar > & Next(lang::Whitespaces trimming=lang::Whitespaces::Trim, TChar newDelim='\0')
Definition tokenizer.cpp:16
TSubstring< TChar > Actual
Definition tokenizer.hpp:73
#define ALIB_CALLER_NULLED
Definition alib.hpp:1173
#define A_CHAR(STR)
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:1271
#define ALIB_DBG(...)
Definition alib.hpp:390
Definition alib.cpp:69
lang::Exception Exception
Type alias in namespace alib.
characters::character character
Type alias in namespace alib.
constexpr String NULL_STRING
A nulled string of the default character type.
Definition string.hpp:2549
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:273
See sibling type NC.
Definition alib.hpp:1097
List< MonoAllocator, Parameter *, Recycling::Shared > ParametersMandatory
Mandatory parameters parsed.
ALIB_API Parameter * GetParsedParameter(const String &name)
ALIB_API bool Read(CommandDecl &decl)
ALIB_API String GetParsedParameterArg(const String &name)
List< MonoAllocator, Parameter *, Recycling::Shared > ParametersOptional
Optional parameters parsed.
String parameters
List of parameters attached. Separated by '/'.
bool isOptional
Denotes if this is an optional parameter.
Definition arguments.hpp:82
String identifier
The identifier of the parameter.
Definition arguments.hpp:64
ALIB_API void Parse()
Implementation of EnumRecordPrototype::Parse.
List< MonoAllocator, String, Recycling::Shared > Args
Arguments belonging to this option.
ALIB_API bool Read(OptionDecl &decl, String &arg, const integer argNo)
Definition arguments.cpp:59
A declaration for a cli::Parameter.
List< MonoAllocator, String, Recycling::Shared > Args
Arguments belonging to us.
ALIB_API bool Read(ParameterDecl &decl)
CommandLine * CmdLine
The cli command line.
Definition arguments.hpp:34
integer ConsumedArguments
Definition arguments.hpp:43
static ALIB_API void Get(String &result, bool isLastField=false)