Add ignore_uknown option processing

This commit is contained in:
zawz 2020-01-31 15:44:45 +01:00
parent 5c46026ea5
commit 0be51b3671
3 changed files with 48 additions and 26 deletions

1
.gitignore vendored
View file

@ -3,3 +3,4 @@ obj_so
libztd.a libztd.a
libztd.so libztd.so
doc doc
Zmakefile

View file

@ -143,14 +143,15 @@ namespace ztd
@param arguments vector of string containing arguments and options @param arguments vector of string containing arguments and options
@param ignore_numbers negative numbers are not considered as options @param ignore_numbers negative numbers are not considered as options
@param stop_on_argument stop processing when encountering a non-option argument @param stop_on_argument stop processing when encountering a non-option argument
@param ignore_unknown don't throw exceptions on unknown options, instead append to return arguments
@return if @a stop_on_argument unprocessed arguments\n else leftover arguments that are not options\n @return if @a stop_on_argument unprocessed arguments\n else leftover arguments that are not options\n
*/ */
std::vector<std::string> process(std::vector<std::string> arguments, bool ignore_numbers=false, bool stop_on_argument=false); std::vector<std::string> process(std::vector<std::string> arguments, bool ignore_numbers=false, bool stop_on_argument=false, bool ignore_unknown=false);
//! @brief Process arguments through the option set //! @brief Process arguments through the option set
/*! /*!
calls process(std::vector<std::string> arguments, bool ignore_numbers, bool stop_on_argument) @see process(std::vector<std::string> arguments, bool ignore_numbers, bool stop_on_argument, bool ignore_unknown)
*/ */
inline std::vector<std::string> process(int argc, char** argv, bool ignore_numbers=false, bool stop_on_argument=false) { return this->process(ztd::argVector(argc, argv), ignore_numbers, stop_on_argument); } inline std::vector<std::string> process(int argc, char** argv, bool ignore_numbers=false, bool stop_on_argument=false, bool ignore_unknown=false) { return this->process(ztd::argVector(argc, argv), ignore_numbers, stop_on_argument, ignore_unknown); }
//! @brief Get option with char name //! @brief Get option with char name
/*! @see option* find(char c) /*! @see option* find(char c)

View file

@ -160,61 +160,72 @@ ztd::option* ztd::option_set::find(const std::string& str)
return nullptr; return nullptr;
} }
std::vector<std::string> ztd::option_set::process(std::vector<std::string> arguments, bool ignore_numbers, bool stop_on_argument) std::vector<std::string> ztd::option_set::process(std::vector<std::string> arguments, bool ignore_numbers, bool stop_on_argument, bool ignore_unknown)
{ {
std::vector<std::string> out; std::vector<std::string> out;
unsigned int i=0; unsigned int i=0;
option_sequence.clear(); option_sequence.clear();
for( auto it = arguments.begin(); it!=arguments.end() ; it++ ) for( auto it = arguments.begin(); it!=arguments.end() ; it++ )
{ {
// arg is option
if( (*it).size()>0 && (*it)[0]=='-' ) if( (*it).size()>0 && (*it)[0]=='-' )
{ {
// -- opt
if((*it).size()>1 && (*it)[1]=='-') if((*it).size()>1 && (*it)[1]=='-')
{ {
std::size_t eqn=(*it).find('='); std::size_t eqn=(*it).find('=');
if(eqn == std::string::npos) if(eqn == std::string::npos) // no arg =
{ {
ztd::option* popt = this->find( (*it).substr(2,eqn-2) ); ztd::option* popt = this->find( (*it).substr(2,eqn-2) );
if(popt == nullptr) if(popt == nullptr) // unknown -- opt
{ {
if(!ignore_unknown)
throw ztd::option_error(ztd::option_error::unknown_option, "--" + (*it).substr(2,eqn-2)); throw ztd::option_error(ztd::option_error::unknown_option, "--" + (*it).substr(2,eqn-2));
// add to ret if ignore
out.push_back(*it);
} }
if(popt->takesArgument) else if(popt->takesArgument) // arg needed
{ {
if( ++it == arguments.end() ) //finishes here if( ++it == arguments.end() ) // no arg given
{ {
throw ztd::option_error(ztd::option_error::missing_arg, "--" + popt->strName); throw ztd::option_error(ztd::option_error::missing_arg, "--" + popt->strName);
} }
// take next arg as arg
popt->activated = true; popt->activated = true;
popt->argument = (*it); popt->argument = (*it);
option_sequence.push_back(*popt); option_sequence.push_back(*popt);
} }
else else // no arg needed
{ {
popt->activated = true; popt->activated = true;
option_sequence.push_back(*popt); option_sequence.push_back(*popt);
} }
} }
else else // there is =
{ {
ztd::option* popt = this->find( (*it).substr(2,eqn-2) ); ztd::option* popt = this->find( (*it).substr(2,eqn-2) );
if(popt == nullptr) if(popt == nullptr) // unknown -- opt
{ {
if(!ignore_unknown)
throw ztd::option_error(ztd::option_error::unknown_option, "--" +(*it).substr(2,eqn-2)); throw ztd::option_error(ztd::option_error::unknown_option, "--" +(*it).substr(2,eqn-2));
// add to ret if ignore
out.push_back(*it);
} }
if(!popt->takesArgument) if(!popt->takesArgument) // opt doesn't take arg
{ {
throw ztd::option_error(ztd::option_error::takes_no_arg, "--" + popt->strName); throw ztd::option_error(ztd::option_error::takes_no_arg, "--" + popt->strName);
} }
// take = as arg
popt->activated = true; popt->activated = true;
popt->argument = (*it).substr(eqn+1,(*it).size()-eqn-1 ); popt->argument = (*it).substr(eqn+1,(*it).size()-eqn-1 );
option_sequence.push_back(*popt); option_sequence.push_back(*popt);
} }
} }
else else // - opt
{ {
i=1; i=1;
if( ignore_numbers && (*it)[i] >= '0' && (*it)[i] <= '9') if( ignore_numbers && (*it)[i] >= '0' && (*it)[i] <= '9') // ignore numbers : add as ret arg
{ {
while(it!=arguments.end() && (*it).size()>i) while(it!=arguments.end() && (*it).size()>i)
i++; i++;
@ -222,34 +233,39 @@ std::vector<std::string> ztd::option_set::process(std::vector<std::string> argum
return std::vector<std::string>(it, arguments.end()); return std::vector<std::string>(it, arguments.end());
out.push_back(*it); out.push_back(*it);
} }
else else // opt
{ {
ztd::option* popt=nullptr; ztd::option* popt=nullptr;
bool tstop=false; bool tstop=false;
while( !tstop && it!=arguments.end() && (*it).size()>i ) std::string ropt; // ignored opts
while( !tstop && it!=arguments.end() && (*it).size()>i ) // iterate all chars of arg
{ {
popt=this->find((*it)[i]); popt=this->find((*it)[i]);
if(popt==nullptr) //not found: error if(popt==nullptr) // unknown opt
{ {
if(!ignore_unknown)
throw ztd::option_error(ztd::option_error::unknown_option, std::string("-") + (*it)[i] ); throw ztd::option_error(ztd::option_error::unknown_option, std::string("-") + (*it)[i] );
// add to ret if ignore
ropt += *it;
} }
if(popt->takesArgument) //no argument if(popt->takesArgument) // needs arg
{ {
i++; i++;
if((*it).size()<=i) //finishes here if((*it).size()<=i) // finishes here
{ {
if( ++it == arguments.end() ) if( ++it == arguments.end() ) // no arg given
{ {
throw ztd::option_error(ztd::option_error::missing_arg, std::string("-") + popt->charName ); throw ztd::option_error(ztd::option_error::missing_arg, std::string("-") + popt->charName );
} }
// take next arg as arg
popt->activated = true; popt->activated = true;
popt->argument = (*it); popt->argument = (*it);
option_sequence.push_back(*popt); option_sequence.push_back(*popt);
tstop = true; tstop = true;
} }
else //continue else // take rest as arg
{ {
if( (*it)[i] == '=') if( (*it)[i] == '=') // ignore = char
i++; i++;
popt->argument = (*it).substr(i , (*it).size()-i ); popt->argument = (*it).substr(i , (*it).size()-i );
popt->activated = true; popt->activated = true;
@ -257,13 +273,17 @@ std::vector<std::string> ztd::option_set::process(std::vector<std::string> argum
tstop=true; tstop=true;
} }
} }
else //no argument else // needs no arg
{ {
popt->activated = true; popt->activated = true;
option_sequence.push_back(*popt); option_sequence.push_back(*popt);
} }
i++; i++;
} //while } //while
if(ropt.size() > 0) // ignored opts: append them to ret
out.push_back("-" + ropt);
} // if not number } // if not number
} }
} }