/* PIP - Platform Independent Primitives Command-Line Parser Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #include "picli.h" #include "pisysteminfo.h" #include "pitranslator.h" //! \class PICLI picli.h //! \details //! \~english \section PICLI_sec0 Synopsis //! \~russian \section PICLI_sec0 Краткий обзор //! \~english //! This class provide handy parsing of command-line arguments. First you should add //! arguments to %PICLI with function \a addArgument(). Then you can check if there //! is some argument in application command-line with function \a hasArgument(), //! or obtain argument value by \a argumentValue(). //! //! \~russian //! Этот класс предоставляет удобный механизм для разбора аргументов командной строки. //! Сперва необходимо добавить аргументы в %PICLI с помощью методов \a addArgument(). //! Далее можно проверять аргументы на наличие в командной строке методом \a hasArgument(), //! а также получать их значения при помощи \a argumentValue(). //! //! \~english \section PICLI_sec1 Example //! \~russian \section PICLI_sec1 Пример //! \~\code //! int main(int argc, char ** argv) { //! PICLI cli(argc, argv); //! cli.addArgument("console"); //! cli.addArgument("debug"); //! cli.addArgument("Value", "v", "value", true); //! if (cli.hasArgument("console")) //! piCout << "console active"; //! if (cli.hasArgument("debug")) //! piCout << "debug active"; //! piCout << "Value =" << cli.argumentValue("Value"); //! return 0; //! } //! \endcode //! //! \~english These executions are similar: //! \~russian Эти вызовы будут идентичны: //! //! \~\code //! a.out -cd -v 10 //! a.out --value 10 -dc //! a.out -c -v 10 -d //! a.out --console -d -v 10 //! a.out --debug -c --value 10 //! \endcode //! PICLI::PICLI(int argc, char * argv[]) { for (int i = 0; i < argc; ++i) _args_raw << argv[i]; if (argc > 0) PISystemInfo::instance()->execCommand = argv[0]; } void PICLI::parse() { if (!needParse) return; PIString cra, full; Argument * last = 0; for (int i = 1; i < _args_raw.size_s(); ++i) { cra = _args_raw[i]; if (cra.left(2) == _prefix_full) { last = 0; full = cra.right(cra.length() - 2); for (auto & a: _args) { if (a.full_key == full) { a.found = true; last = &a; break; } } } else { if (cra.left(1) == _prefix_short) { last = 0; for (int j = 1; j < cra.length(); ++j) { bool found = false; for (auto & a: _args) { if ((a.short_key != '\0') && (a.short_key == cra[j])) { a.found = true; last = &a; found = true; break; } } if (!found) break; } } else { if (last == 0 ? true : !last->has_value) { if (_args_mand.size_s() < _count_mand) { _args_mand << cra; continue; } if (_args_opt.size_s() < _count_opt || _count_opt < 0) { _args_opt << cra; continue; } piCoutObj << "Arguments overflow, \"%1\" ignored"_tr("PICLI").arg(cra); } if (last == 0 ? false : last->has_value) { last->value = cra; last = 0; } } } } needParse = false; } void PICLI::addArgument(const PIString & name, bool value) { _args << Argument(name, name[0], name, value); needParse = true; } void PICLI::addArgument(const PIString & name, const PIChar & shortKey, bool value) { _args << Argument(name, shortKey, name, value); needParse = true; } void PICLI::addArgument(const PIString & name, const char * shortKey, bool value) { _args << Argument(name, PIChar::fromUTF8(shortKey), name, value); needParse = true; } void PICLI::addArgument(const PIString & name, const PIChar & shortKey, const PIString & fullKey, bool value) { _args << Argument(name, shortKey, fullKey, value); needParse = true; } void PICLI::addArgument(const PIString & name, const char * shortKey, const PIString & fullKey, bool value) { _args << Argument(name, PIChar::fromUTF8(shortKey), fullKey, value); needParse = true; } PIString PICLI::rawArgument(int index) { parse(); return _args_raw[index]; } PIString PICLI::mandatoryArgument(int index) { parse(); return _args_mand[index]; } PIString PICLI::optionalArgument(int index) { parse(); return _args_opt[index]; } const PIStringList & PICLI::rawArguments() { parse(); return _args_raw; } const PIStringList & PICLI::mandatoryArguments() { parse(); return _args_mand; } const PIStringList & PICLI::optionalArguments() { parse(); return _args_opt; } PIString PICLI::programCommand() { parse(); return _args_raw.isNotEmpty() ? _args_raw.front() : PIString(); } bool PICLI::hasArgument(const PIString & name) { parse(); for (const auto & i: _args) if (i.name == name && i.found) return true; return false; } PIString PICLI::argumentValue(const PIString & name) { parse(); for (const auto & i: _args) if (i.name == name && i.found) return i.value; return PIString(); } PIString PICLI::argumentShortKey(const PIString & name) { for (const auto & i: _args) if (i.name == name) return PIString(i.short_key); return PIString(); } PIString PICLI::argumentFullKey(const PIString & name) { for (const auto & i: _args) if (i.name == name) return i.full_key; return PIString(); } void PICLI::setShortKeyPrefix(const PIString & prefix) { _prefix_short = prefix; needParse = true; } void PICLI::setFullKeyPrefix(const PIString & prefix) { _prefix_full = prefix; needParse = true; } void PICLI::setMandatoryArgumentsCount(const int count) { _count_mand = count; needParse = true; } void PICLI::setOptionalArgumentsCount(const int count) { _count_opt = count; needParse = true; }