#include "argsparser.h" #include using namespace args_parse; using namespace std; __ArgvPackImpls::__ArgvPackImpls(const QString& means, ParamType t) : means_store(means), type_store(t) { } // 通过 IArgvPack 继承 ParamType __ArgvPackImpls::paramType() const { return type_store; } QString __ArgvPackImpls::means() const { return means_store; } void __ArgvPackImpls::setValue(const QVariant& v) { this->value_store = v; } QVariant __ArgvPackImpls::value() const { return value_store; } FloatKeyValue::FloatKeyValue(const QString& key, const QString& means, bool optional) : __FloatArgvImpls(key, means, optional) { } QString __FloatArgvImpls::bindKey() const { return key_name; } bool __FloatArgvImpls::optional() const { return optional_value; } QString FloatKeyValue::placeHolder(bool v) const { if (optional() && v) return QString("[--%1 <%2>]").arg(bindKey(), bindKey()); return QString("--%1 <%2>").arg(bindKey(), bindKey()); } int FloatKeyValue::matchLenth() const { return 2; } bool FloatKeyValue::parse(const QList args) { if (args.size() < 2) return false; auto args_t = args[0]; if (args_t == "--" + bindKey()) { auto args_v = args[1]; setValue(args_v); return true; } return false; } IndexParam::IndexParam(const QString& place_v, const QString& means) : __ArgvPackImpls(means, ParamType::IndexParam), _place_holder(place_v) { } QString IndexParam::placeHolder(bool v) const { return QString("<%1>").arg(_place_holder); } int IndexParam::matchLenth() const { return 1; } bool IndexParam::parse(const QList args) { if (args.size() < 1) return false; setValue(args[0]); return true; } __FloatArgvImpls::__FloatArgvImpls(const QString& key, const QString& means, bool optional) : __ArgvPackImpls(means, ParamType::FloatParam), key_name(key), optional_value(optional) { } FloatOption::FloatOption(const QString& key, const QString& means, bool opt) : __FloatArgvImpls(key, means, opt) { } QString FloatOption::placeHolder(bool d) const { if (optional() && d) return QString("[--%1]").arg(bindKey()); return QString("--%1").arg(bindKey()); } int FloatOption::matchLenth() const { return 1; } bool FloatOption::parse(const QList args) { if (args.size() < 1) return false; auto args_t = args[0]; if (args_t == "--" + bindKey()) { setValue(true); return true; } return false; } MatchMode::MatchMode(int mode_code, const QString& mode) :_means_explain(mode), code_store(mode_code) { } #include class inner_exception : public std::exception { private: QByteArray _message; public: inner_exception(const QString &msg) :_message(msg.toUtf8()){} virtual const char* what() const noexcept{ return _message.data(); } }; MatchMode& MatchMode::operator<<(std::shared_ptr unit) { if(unit->paramType() == ParamType::FloatParam){ auto unit_in = std::dynamic_pointer_cast<__FloatArgvImpls>(unit); for (auto& u_exist : args_mode) { if (u_exist->paramType() == ParamType::FloatParam) { auto u_cast = std::dynamic_pointer_cast<__FloatArgvImpls>(u_exist); if (u_cast->bindKey() == unit_in->bindKey()) throw new inner_exception("重复设置选项"); } } } args_mode << unit; return *this; } int MatchMode::modeCode() const { return code_store; } QString MatchMode::usagestring() const { QString usage_string; for (auto& item : args_mode) usage_string += item->placeHolder() + " "; return usage_string; } QString MatchMode::explanstring() const { QStringList sections; sections << " " + _means_explain; sections << QString(" Switch:"); for (auto& item : args_mode) { if (item->paramType() == ParamType::IndexParam) { sections << " " + item->placeHolder(false); sections << " " + item->means(); } } for (auto& item : args_mode) { if (item->paramType() == ParamType::FloatParam) { sections << " " + item->placeHolder(false); sections << " " + item->means(); } } return sections.join("\n"); } /** * @brief 解析匹配参数 */ bool MatchMode::parse(const QList& args) { decltype(this->args_mode) float_units; std::copy_if(this->args_mode.begin(), this->args_mode.end(), std::back_inserter(float_units), [](std::shared_ptr inst) { return inst->paramType() == ParamType::FloatParam; }); auto remains = args; for (auto idx = 0; idx < remains.size(); ++idx) { auto vargs = remains.mid(idx); for (auto& unit : float_units) { if (unit->parse(vargs)) { auto it_start = remains.begin() + idx; auto it_until = it_start + unit->matchLenth(); remains.erase(it_start, it_until); idx--; break; } } } decltype(this->args_mode) indexed_units; std::copy_if(this->args_mode.begin(), this->args_mode.end(), std::back_inserter(indexed_units), [](std::shared_ptr inst) { return inst->paramType() == ParamType::IndexParam; }); for (auto idx = 0; idx < std::min(remains.size(), indexed_units.size()); ++idx) { auto vargs = remains.mid(idx); auto unit = indexed_units[idx]; unit->parse(vargs); } for (auto& u : args_mode) { switch (u->paramType()) { case ParamType::IndexParam: if (u->value().isNull()) return false; break; case ParamType::FloatParam: if (!std::dynamic_pointer_cast<__FloatArgvImpls>(u)->optional() && u->value().isNull()) return false; break; default: break; } } return true; } std::shared_ptr MatchMode::getUnitViaKey(const QString& key) { for (auto& u : args_mode) { if (u->paramType() == ParamType::FloatParam) { auto conv = std::dynamic_pointer_cast<__FloatArgvImpls>(u); if (conv->bindKey() == key) return u; } } return std::shared_ptr(); } std::shared_ptr MatchMode::getUnitViaInitIndex(int pos) { return args_mode[pos]; } QString ArgsParser::helperDoc() const { QString help_string; for (auto& mode : this->match_modes) { help_string += "Usage:" + mode->usagestring() + "\n"; help_string += mode->explanstring() + "\n\n"; } return help_string; } ArgsParser& ArgsParser::operator<<(std::shared_ptr mode) { this->match_modes.append(mode); return *this; } std::shared_ptr ArgsParser::parse(int argc, char* argv[]) { // 聚合参数数组 QList args_list; for (int idx = 0; idx < argc; idx++) { auto argv_str = QString::fromLocal8Bit(argv[idx]); args_list.append(argv_str); } // 枚举模式匹配 for (auto& minst : this->match_modes) { if (minst->parse(args_list)) return minst; } return std::shared_ptr(); }