diff --git a/.gitignore b/.gitignore index 9a1c20c..df72eb1 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ obj_so libztd.a libztd.so doc +Zmakefile diff --git a/include/options.hpp b/include/options.hpp index b9ade15..03c82bd 100644 --- a/include/options.hpp +++ b/include/options.hpp @@ -143,14 +143,15 @@ namespace ztd @param arguments vector of string containing arguments and options @param ignore_numbers negative numbers are not considered as options @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 */ - std::vector process(std::vector arguments, bool ignore_numbers=false, bool stop_on_argument=false); + std::vector process(std::vector arguments, bool ignore_numbers=false, bool stop_on_argument=false, bool ignore_unknown=false); //! @brief Process arguments through the option set /*! - calls process(std::vector arguments, bool ignore_numbers, bool stop_on_argument) + @see process(std::vector arguments, bool ignore_numbers, bool stop_on_argument, bool ignore_unknown) */ - inline std::vector 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 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 /*! @see option* find(char c) diff --git a/src/options.cpp b/src/options.cpp index 6805f95..55c704d 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -160,61 +160,72 @@ ztd::option* ztd::option_set::find(const std::string& str) return nullptr; } -std::vector ztd::option_set::process(std::vector arguments, bool ignore_numbers, bool stop_on_argument) +std::vector ztd::option_set::process(std::vector arguments, bool ignore_numbers, bool stop_on_argument, bool ignore_unknown) { std::vector out; unsigned int i=0; option_sequence.clear(); for( auto it = arguments.begin(); it!=arguments.end() ; it++ ) { + // arg is option if( (*it).size()>0 && (*it)[0]=='-' ) { + + // -- opt if((*it).size()>1 && (*it)[1]=='-') { 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) ); - if(popt == nullptr) + if(popt == nullptr) // unknown -- opt { - throw ztd::option_error(ztd::option_error::unknown_option, "--" + (*it).substr(2,eqn-2)); + if(!ignore_unknown) + 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); } + // take next arg as arg popt->activated = true; popt->argument = (*it); option_sequence.push_back(*popt); } - else + else // no arg needed { popt->activated = true; option_sequence.push_back(*popt); } } - else + else // there is = { ztd::option* popt = this->find( (*it).substr(2,eqn-2) ); - if(popt == nullptr) + if(popt == nullptr) // unknown -- opt { - throw ztd::option_error(ztd::option_error::unknown_option, "--" +(*it).substr(2,eqn-2)); + if(!ignore_unknown) + 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); } + // take = as arg popt->activated = true; popt->argument = (*it).substr(eqn+1,(*it).size()-eqn-1 ); option_sequence.push_back(*popt); } } - else + else // - opt { 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) i++; @@ -222,34 +233,39 @@ std::vector ztd::option_set::process(std::vector argum return std::vector(it, arguments.end()); out.push_back(*it); } - else + else // opt { ztd::option* popt=nullptr; 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]); - if(popt==nullptr) //not found: error + if(popt==nullptr) // unknown opt { - throw ztd::option_error(ztd::option_error::unknown_option, std::string("-") + (*it)[i] ); + if(!ignore_unknown) + 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++; - 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 ); } + // take next arg as arg popt->activated = true; popt->argument = (*it); option_sequence.push_back(*popt); tstop = true; } - else //continue + else // take rest as arg { - if( (*it)[i] == '=') + if( (*it)[i] == '=') // ignore = char i++; popt->argument = (*it).substr(i , (*it).size()-i ); popt->activated = true; @@ -257,13 +273,17 @@ std::vector ztd::option_set::process(std::vector argum tstop=true; } } - else //no argument + else // needs no arg { popt->activated = true; option_sequence.push_back(*popt); } i++; } //while + + if(ropt.size() > 0) // ignored opts: append them to ret + out.push_back("-" + ropt); + } // if not number } }