ALib C++ Library
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
commandline.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 ========================================
15#include "alib/alib.inl"
16//============================================== Module ============================================
17#if ALIB_C20_MODULES
18 module ALib.CLI;
19 import ALib.Characters.Functions;
20# if ALIB_STRINGS
21 import ALib.Strings;
22# endif
23#else
25# include "ALib.Strings.H"
26# include "ALib.CLI.H"
27#endif
28//========================================== Implementation ========================================
29namespace alib::cli {
30
31//##################################################################################################
32// CommandLine Constructor
33//##################################################################################################
34
35void CommandLine::Init( resources::ResourcePool* resourcePool, NCString resCategory ) {
36 Resources = resourcePool;
37 ResourceCategory= resCategory;
38
39 ArgStrings.reserve( size_t(ARG_C) );
40 ArgsLeft .reserve( size_t(ARG_C) );
41
42 #if !ALIB_CHARACTERS_WIDE
43 if( ARG_VN ) {
44 for ( int i= 1; i < ARG_C ; ++i ) {
45 ArgStrings.emplace_back( ARG_VN[i] );
46 ArgsLeft .emplace_back( i -1 );
47 }
48 } else {
49 // convert wide to narrow strings
50 NString1K converter;
52
53 for ( int i= 1; i < ARG_C ; ++i ) {
54 converter.Reset() << ARG_VW[i];
55 ArgStrings.emplace_back( String( allocator, converter) );
56 ArgsLeft .emplace_back( i - 1 );
57 } }
58 #else
59 #if ALIB_CHARACTERS_NATIVE_WCHAR // use original strings only if alib::wchar == wchar_t
60 if( ARG_VW ) {
61 for ( int i= 1; i < ARG_C ; ++i ) {
62 ArgStrings.emplace_back( ARG_VW[i] );
63 ArgsLeft .emplace_back( i - 1 );
64 } }
65 else
66 #endif
67 {
68 // convert narrow to wide strings (or "wrong" wide width to width)
69 String1K converter;
71
72 for ( int i= 1; i < ARG_C ; ++i ) {
73 converter.Reset() << ARG_VN[i];
74 ArgStrings.emplace_back( String(allocator, converter) );
75 ArgsLeft .emplace_back( i -1 );
76 } }
77 #endif
78}
79
80//##################################################################################################
81// Interface
82//##################################################################################################
83
85 // loop over all arg indices in ArgsLeft
86 integer argIdx= 0;
87 while( argIdx < integer(ArgsLeft.size()) ) {
88 // get arg number and string once
89 auto argNo= ArgsLeft[size_t(argIdx)];
90 String arg = GetArg(argNo);
91
92 SHORTCUT_JUMP:
93
94 // ignore non-option args
95 if( arg.CharAtStart() != '-' ) {
96 ++argIdx;
97 continue;
98 }
99
100 // create an option object and search decl with the actual argument
101 {
102 Option* option= allocator().New<Option>(this);
103
104 auto optionDeclIt= OptionDecls.begin();
105 try
106 {
107 while( optionDeclIt != OptionDecls.end() ) {
108 if( option->Read( **optionDeclIt, arg, argNo ) )
109 break;
110 ++optionDeclIt;
111 } }
112 catch ( Exception& e )
113 {
115 (*optionDeclIt)->HelpUsageLine() );
116 throw;
117 }
118
119 // found a declaration?
120 if( option->ConsumedArguments > 0 ) {
121 // shortcut to another option?
122 OptionDecl& decl= *option->Declaration;
124 arg= decl.ShortcutReplacementString();
125 goto SHORTCUT_JUMP;
126 }
127
128 // delete args and continue
129 ArgsLeft.erase( ArgsLeft.begin() + argIdx,
130 ArgsLeft.begin() + argIdx + option->ConsumedArguments );
131
132 // move local option into the monotonic memory add to the list for this option type.
133 Options.push_back( option );
134 continue;
135 }
136
137
138 // erase args that start with '-' and put them into field OptionsIgnored.
139 if( ArgsLeft.size() > 0 ) {
140 OptionArgsIgnored.push_back( GetArg(argNo) );
141 ArgsLeft.erase( ArgsLeft.begin() + argIdx );
142} } } }
143
145 for( auto optionIt= Options.rbegin() ; optionIt != Options.rend() ; optionIt ++ )
146 if( (*optionIt)->Declaration->Element() == element )
147 return *optionIt;
148 return nullptr;
149}
150
151
153 // loop over all arg indices in ArgsLeft
154 bool lastCommandFullyParsed= true;
155 while( lastCommandFullyParsed && ArgsLeft.size() > 0 ) {
156 // create a command object and search decl with actual argument
157 Command* command= allocator().New<Command>(this);
158 ALIB_ASSERT_ERROR( CommandDecls.size() > 0, "CLI", "No commands declared." )
159 for( auto* commandDecl : CommandDecls ) {
160 try
161 {
162 lastCommandFullyParsed= command->Read( *commandDecl );
163 }
164 catch ( Exception& e )
165 {
167 CLIUtil::GetCommandUsageFormat( *this, *commandDecl ),
168 commandDecl->HelpTextShort() );
169 throw;
170 }
171
172 if( command->ConsumedArguments > 0 ) {
173 CommandsParsed.push_back( command );
174 if( NextCommandIt == CommandsParsed.end() )
176 break;
177} } } }
178
180 if( NextCommandIt == CommandsParsed.end() )
182 if( NextCommandIt == CommandsParsed.end() ) {
183 // check for arguments left which got not recognized
184 if( ArgsLeft.size() > 0 )
186 ArgsLeft[0], PeekArg() );
187
188 // check for no command
189 if ( CommandsParsed.empty() )
191
192 return nullptr;
193 }
194
195 auto* result= *NextCommandIt;
197 return result;
198}
199
200
202 if( ArgsLeft.size() == 0)
203 return NULL_STRING;
204
205 String result= GetArg(ArgsLeft[0]);
206 ArgsLeft.erase( ArgsLeft.begin() );
207 return result;
208}
209
211 for( auto it= ArgsLeft.begin() ; it != ArgsLeft.end() ; ++it )
212 if( *it == argNo ) {
213 ArgsLeft.erase( it );
214 return;
215 }
216 ALIB_ERROR( "CLI", "Argument number {} already removed.", argNo )
217}
218
219
220
221} // namespace alib::cli
static ALIB_DLL AString GetCommandUsageFormat(CommandLine &cmdLine, CommandDecl &commandDecl)
Definition cliutil.cpp:62
virtual String PeekArg()
ALIB_DLL void RemoveArg(integer argNo)
virtual ALIB_DLL void ReadOptions()
virtual ALIB_DLL void ReadNextCommands()
StdVectorMA< integer > ArgsLeft
ALIB_DLL Option * GetOption(Enum element)
ListMA< String, Recycling::Shared > OptionArgsIgnored
MonoAllocator allocator
StdVectorMA< String > ArgStrings
void Init(camp::Camp *resModule)
ListMA< CommandDecl * > CommandDecls
Commands defined.
ListMA< Command * > CommandsParsed
A list of commands actually parsed. Filled with method ReadNextCommands.
ListMA< Option * > Options
The options parsed in the order of their appearance.
NCString ResourceCategory
The resource category to fetch CLI resources within field Resources.
ListMA< Command * >::iterator NextCommandIt
The next command in CommandsParsed to be processed. Used with method NextCommand.
ListMA< OptionDecl * > OptionDecls
Possible Options.
resources::ResourcePool * Resources
virtual ALIB_DLL String PopArg()
virtual ALIB_DLL Command * NextCommand()
virtual String GetArg(integer idx)
const String & ShortcutReplacementString()
Exception & Add(const lang::CallerInfo &ci, TEnum type, TArgs &&... args)
void DbgDisableBufferReplacementWarning()
Definition tastring.inl:244
TChar CharAtStart() const
Definition string.inl:433
constexpr bool IsNotEmpty() const
Definition string.inl:369
#define ALIB_CALLER_NULLED
Definition alib.inl:1027
#define ALIB_ERROR(domain,...)
Definition alib.inl:1062
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1066
@ ParsingOptions
General option parse error. Adds option help text.
Definition clicamp.inl:53
@ ParsingCommand
General parameter parse error. Adds command help text.
Definition clicamp.inl:54
@ NoCommandGiven
Unknown command given.
Definition clicamp.inl:51
@ UnknownCommand
Unknown command given.
Definition clicamp.inl:52
constexpr String NULL_STRING
A nulled string of the default character type.
Definition string.inl:2271
const wchar_t ** ARG_VW
Definition mainargs.cpp:25
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
NLocalString< 1024 > NString1K
Type alias name for TLocalString<nchar,1024>.
strings::TCString< nchar > NCString
Type alias in namespace alib.
Definition cstring.inl:484
boxing::Enum Enum
Type alias in namespace alib.
Definition enum.inl:192
LocalString< 1024 > String1K
Type alias name for TLocalString<character,1024>.
exceptions::Exception Exception
Type alias in namespace alib.
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2189
const char ** ARG_VN
Definition mainargs.cpp:24
int ARG_C
Definition mainargs.cpp:23
A command of a ALib CLI command line.
ALIB_DLL bool Read(CommandDecl &decl)
OptionDecl * Declaration
The declaration struct.
ALIB_DLL bool Read(OptionDecl &decl, String &arg, const integer argNo)
Definition arguments.cpp:64
integer ConsumedArguments
Definition arguments.inl:35