#ifndef YERBACON_ARGUMENTS_HPP #define YERBACON_ARGUMENTS_HPP #include #include #include #include #include using namespace std; class Argument { protected: const string longVersion; virtual bool is(string_view str) { bool hasPrefix = str.starts_with("--"); if (hasPrefix) str.remove_prefix(2); return (not str.empty()) && longVersion == str && hasPrefix; } public: bool operator ==(const string_view it) { return is(it); } explicit Argument(string name): longVersion(move(name)) {} }; class ArgumentAssignable: public Argument { vector values; public: static string getValueFor(const string& str) { unsigned long definePos = str.find_last_of('=') + 1; return str.size() > definePos ? str.substr(definePos) : string(); } ArgumentAssignable(string name, const span& possibleValues) : Argument(move(name)), values() { values.reserve(possibleValues.size()); move(possibleValues.begin(), possibleValues.end(), back_inserter(values)); } explicit ArgumentAssignable(const string& name): ArgumentAssignable(name, span()) {}; // To use when we don't want the argument's possible values to be checked protected: bool is(string_view str) override { if (str.find_last_of('=') != string_view::npos && !str.empty()) { auto isValid = [&]() -> bool { return str.starts_with("--" + longVersion + '='); }; if (values.empty()) return isValid(); for (const auto& value : values) { if (str.ends_with(value.substr(1, value.size()))) { return isValid(); } } } return false; } }; struct ArgumentShort: public Argument { const string shortVersion; ArgumentShort(string shortName, string name): Argument(move(name)), shortVersion(move(shortName)) {} explicit ArgumentShort(string name): ArgumentShort(string(1, name.at(0)), name) {} protected: bool is(string_view string) override { return Argument::is(string) || (!string.empty() && shortVersion == string.substr(1, string.size())); } }; #endif //YERBACON_ARGUMENTS_HPP