ALib C++ Framework
by
Library Version: 2605 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
cliargtypes.cpp
1
2namespace alib { namespace app {
3
4//##################################################################################################
5// ### Methods of Command, Option, etc.
6//##################################################################################################
7
9 Tokenizer tknzr( record.parameters , '/' );
10 while( tknzr.Next().IsNotEmpty() ) {
11ALIB_DBG( bool found= false; )
12
13 for( auto* paramDecl : CmdLine.ParameterDecls )
14 if( paramDecl->Name().StartsWith<CHK, lang::Case::Ignore>( tknzr.Actual ) ) {
15 Parameters.push_back( paramDecl );
16 ALIB_DBG(found= true; )
17 break;
18 }
19
20 ALIB_ASSERT_ERROR( found, "CLI",
21 "Parameter named \"{}\" not found while loading resources of command \"{}\".",
22 tknzr.Actual, Identifier() )
23} }
24
26 for( auto* param : Parameters )
27 if( param->Name().Equals<NC>( name ) )
28 return param;
29
30 return nullptr;
31}
32
33
34bool Option::Read( OptionDecl& decl, String& argProbablyReplaced, const integer argNo ) {
35 String identifier = decl.Identifier();
36 character identifierC = decl.IdentifierChar();
37 auto argsExpected= decl.QtyExpectedArgsFollowing();
38 auto argsLeft = CmdLine->ArgsLeft.size() -1;
39
40 // read single/double hyphen options once
41 Substring arg= argProbablyReplaced;
42 Substring inArgArgument;
43 auto valueSeparator= arg.IndexOf<CHK, lang::Case::Sensitive>( decl.ValueSeparator() );
44 if( valueSeparator > 0 )
45 arg.Split<NC>( valueSeparator, inArgArgument, decl.ValueSeparator().Length() );
46
47 bool potentialIllegalContinuation= false;
48 if ( !( ( identifier.IsNotEmpty()
49 && arg.ConsumeString(A_CHAR("--"))
50 && arg.Length() >= decl.MinimumRecognitionLength()
51 && ( identifier.StartsWith<CHK, lang::Case::Ignore>( arg )
52 || true == (potentialIllegalContinuation= arg.StartsWith<CHK,lang::Case::Ignore>( identifier )) )
53
54 )
55
56 || ( arg.ConsumeChar('-')
57 && arg.ConsumeChar(identifierC) )
58 )
59 )
60 return false;
61
62 // Throw if the identifier was fully matched, but the argument continues with a
63 // non-alphanumerical value.
64 // (This is only allowed if separator was set in resource. But in this case, the flag will
65 // never match, because of the code above...)
66 if( potentialIllegalContinuation ) {
67 auto nextChar= arg.CharAt<NC>( identifier.Length() );
68 if( !isalnum( nextChar ) )
70 identifier, argNo, CmdLine->GetArg(argNo) );
71 return false;
72 }
73
74 Declaration= &decl;
75 Position= argNo;
76
78
79
80 // store in-arg argument
81 if( valueSeparator > 0) {
82 Args.push_back( inArgArgument );
83 if(argsExpected > 0 )
84 --argsExpected;
85 }
86
87
88 // error: not enough params
89 if ( argsExpected > integer(argsLeft) )
91 decl.Identifier(), argNo, CmdLine->GetArg(argNo),
92 argsExpected, argsLeft );
93
94 // store arg strings
95 for( integer i= 0; i < argsExpected; ++i )
96 Args.push_back( CmdLine->GetArg(argNo + 1 + i) );
97 ConsumedArguments+= argsExpected;
98
99 return true;
100}
101
103 auto& identifier= decl.Identifier();
104 String arg = CmdLine->PeekArg();
105
106 if ( arg.Length() < decl.MinimumRecognitionLength()
107 || !identifier.StartsWith<CHK,lang::Case::Ignore>( arg ) )
108 return false;
109
110 Declaration= &decl;
111 Position= CmdLine->ArgsLeft[0];
112 CmdLine->PopArg();
114
115 if( decl.Parameters.size() == 0 )
116 return true;
117
118 auto paramDeclIt= decl.Parameters.begin();
119 while( paramDeclIt != decl.Parameters.end() ) {
120 Parameter param( CmdLine );
121 bool continueReading= param.Read( **paramDeclIt );
122 if( param.ConsumedArguments ) {
124 Parameter* paramFound= CmdLine->allocator().New<Parameter>(param);
125 if ( (*paramDeclIt)->IsOptional() )
126 ParametersOptional.push_back( paramFound );
127 else
128 ParametersMandatory.push_back( paramFound );
129
130 // start from the beginning
131 paramDeclIt= decl.Parameters.begin();
132 }
133 else
134 ++paramDeclIt;
135
136 // stop here if parameter read signaled this
137 if( !continueReading )
138 return false;
139 }
140
141 return true;
142}
143
145 #if ALIB_DEBUG
146 bool found= false;
147 for( auto* paramDecl : Declaration->Parameters )
148 if( paramDecl->Name().Equals<NC>(name) ) {
149 found = true;
150 break;
151 }
152 ALIB_ASSERT_ERROR( found, "CLI", "Requested parameter \"{}\" not defined.", name )
153 #endif
154
155 for( auto* param : ParametersMandatory )
156 if( param->Declaration->Name().Equals<NC>( name ) )
157 return param;
158
159 for( auto* param : ParametersOptional )
160 if( param->Declaration->Name().Equals<NC>( name ) )
161 return param;
162
163 return nullptr;
164}
165
167 Parameter* param= GetParsedParameter( name );
168 return param && param->Args.IsNotEmpty() ? param->Args.front()
169 : NULL_STRING;
170}
171
172
174 Substring arg= CmdLine->PeekArg();
175 if( arg.IsNull() )
176 return false;
177
178 auto& identifier= decl.Identifier();
179 if ( identifier.IsEmpty() && decl.IsOptional() )
180 return false;
181
182 auto valueSeparator= arg.IndexOf<CHK, lang::Case::Sensitive>( decl.ValueSeparator() );
183 Substring inArgArgument;
184 if( valueSeparator > 0 )
185 arg.Split<NC>( valueSeparator, inArgArgument, decl.ValueSeparator().Length() );
186
187 if ( identifier.IsEmpty()
188 || ( arg.Length() >= decl.MinimumRecognitionLength()
189 && identifier.StartsWith<CHK,lang::Case::Ignore>( arg ) ) )
190 {
192 Declaration= &decl;
193 Position= CmdLine->ArgsLeft[0];
194 CmdLine->PopArg();
195 int argsExpected= decl.QtyExpectedArgsFollowing();
196
197 if( decl.Identifier().IsEmpty() ) {
198 Args.push_back( arg );
199 } else {
200 if( inArgArgument.IsNotEmpty() ) {
201 Args.push_back( inArgArgument );
202 --argsExpected;
203 } }
204
205 // stop command?
206 if( argsExpected < 0 )
207 return false;
208
209 // error: not enough params
210 if ( argsExpected > integer(CmdLine->ArgsLeft.size()) )
212 decl.Name(), Position, CmdLine->GetArg(Position),
213 argsExpected, CmdLine->ArgsLeft.size() );
214
215 // store arg strings
216 for( size_t i= 0; i < size_t( argsExpected ); ++i ) {
217 Args.push_back( CmdLine->GetArg(*CmdLine->ArgsLeft.begin()) );
218 CmdLine->ArgsLeft.erase( CmdLine->ArgsLeft.begin() );
219 }
220 ConsumedArguments+= size_t( argsExpected );
221 }
222
223
224 return true;
225}
226
227void ERCommandDecl ::Parse() {
228 enumrecords::bootstrap::EnumRecordParser::Get( ERSerializable::EnumElementName );
229 enumrecords::bootstrap::EnumRecordParser::Get( ERSerializable::MinimumRecognitionLength );
231}
232
241
251
252void ERExitCodeDecl ::Parse() {
253 enumrecords::bootstrap::EnumRecordParser::Get( ERSerializable::EnumElementName , true );
254}
255
256}} // namespace alib::app
#define ALIB_CALLER_NULLED
#define A_CHAR(STR)
#define ALIB_DBG(...)
#define ALIB_ASSERT_ERROR(cond, domain,...)
CommandLine & CmdLine
The command-line instance we belong to.
ListMA< ParameterDecl * > Parameters
Command parameters.
ERCommandDecl record
A copy (!) of the enum record.
ParameterDecl * GetParameterDecl(const String &name)
const String & Identifier()
integer QtyExpectedArgsFollowing()
const String & Identifier()
const String & ValueSeparator()
const String & ValueSeparator()
const String & Identifier()
constexpr integer Length() const
Definition string.hpp:300
constexpr bool IsEmpty() const
Definition string.hpp:349
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.hpp:799
TChar CharAt(integer idx) const
Definition string.hpp:399
constexpr bool IsNotEmpty() const
Definition string.hpp:353
constexpr bool IsNull() const
Definition string.hpp:334
bool StartsWith(const TString &needle) const
Definition string.hpp:735
bool ConsumeString(const TString< TChar > &consumable)
TSubstring & Split(integer position, TSubstring &target, integer separatorWidth=0, bool trim=false)
TSubstring< TChar > Actual
Definition tokenizer.hpp:64
TSubstring< TChar > & Next(lang::Whitespaces trimming=lang::Whitespaces::Trim, TChar newDelim='\0')
Definition tokenizer.cpp:4
Definition alox.cpp:14
constexpr String NULL_STRING
A nulled string of the default character type.
Definition string.hpp:2247
strings::util::TTokenizer< character > Tokenizer
Type alias in namespace #"%alib".
lang::integer integer
Type alias in namespace #"%alib".
Definition integers.hpp:149
strings::TString< character > String
Type alias in namespace #"%alib".
Definition string.hpp:2165
strings::TSubstring< character > Substring
Type alias in namespace #"%alib".
exceptions::Exception Exception
Type alias in namespace #"%alib".
characters::character character
Type alias in namespace #"%alib".
See sibling type #"NC".
Definition chk_nc.hpp:30
CommandDecl * Declaration
The underlying declaration.
ListMA< Parameter *, Recycling::Shared > ParametersMandatory
Mandatory parameters parsed.
ListMA< Parameter *, Recycling::Shared > ParametersOptional
Optional parameters parsed.
Parameter * GetParsedParameter(const String &name)
String GetParsedParameterArg(const String &name)
bool Read(CommandDecl &decl)
String parameters
List of parameters attached. Separated by '/'.
String identifier
The identifier of the parameter.
bool isOptional
Denotes if this is an optional parameter.
void Parse()
Implementation of #"EnumRecordPrototype::Parse;*".
bool Read(OptionDecl &decl, String &arg, const integer argNo)
ListMA< String, Recycling::Shared > Args
Arguments belonging to this option.
OptionDecl * Declaration
The declaration struct.
A declaration for a #"app::Parameter".
bool Read(ParameterDecl &decl)
ListMA< String, Recycling::Shared > Args
Arguments belonging to us.
ParameterDecl * Declaration
The underlying declaration.
integer ConsumedArguments
CommandLine * CmdLine
The cli command-line.
static void Get(String &result, bool isLastField=false)