#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 args_parse::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, int start) { auto args_t = args[start]; auto args_v = args[start + 1]; if (args_t == u8"--" + bindKey()) { 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 args_parse::IndexParam::placeHolder(bool v) const { return QString("<%1>").arg(_place_holder); } int IndexParam::matchLenth() const { return 1; } bool IndexParam::parse(const QList args, int start) { setValue(args[start]); 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 args_parse::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, int start) { auto args_t = args[start]; if (args_t == u8"--" + bindKey()) setValue(true); return false; } MatchMode::MatchMode(int mode_code, const QString& mode) :_means_explain(mode), code_store(mode_code) { } /** * @brief 获取模式代码 * @return 模式代码 */ MatchMode& args_parse::MatchMode::operator<<(std::shared_ptr unit) { args_mode << unit; return *this; } int MatchMode::modeCode() const { return code_store; } QString args_parse::MatchMode::usageString() const { QString usage_string; for (auto& item : args_mode) usage_string += item->placeHolder() + u8" "; return usage_string; } QString args_parse::MatchMode::explanString() const { QStringList sections; sections << u8" " + _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, int argv_index, int parse_index) { // 获取模式匹配单元 auto parse_unit = args_mode[parse_index]; switch (parse_unit->paramType()) { case ParamType::IndexParam:// 固定位置索引匹配 { parse_unit->parse(args, argv_index); // 继续匹配下一个为止 return parse(args, argv_index + parse_unit->matchLenth(), parse_index + 1); }break; case ParamType::FloatParam:// 浮动参数匹配 { QList> float_parsers; for (auto& unit : args_mode) { if (unit->paramType() == ParamType::FloatParam) float_parsers << dynamic_pointer_cast<__FloatArgvImpls>(unit); } for (auto& unit : float_parsers) { if (argv_index + unit->matchLenth() > args.size()) continue; auto result = unit->parse(args, argv_index); // 匹配成功 if (result) // 继续下一个 if (parse(args, argv_index + unit->matchLenth(), parse_index + 1)) return true; else if (!result && unit->optional()) if (parse(args, argv_index, parse_index + 1)) return true; } }break; } return false; } std::shared_ptr args_parse::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 args_parse::MatchMode::getUnitViaPos(int pos) { return args_mode[pos]; } QString args_parse::ArgsParser::helpDoc() 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& args_parse::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, 0, 0)) return minst; } return std::shared_ptr(); }