| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
- #pragma once
- #include "cmStringAlgorithms.h"
- #include "cmSystemTools.h"
- template <typename FunctionSignature>
- struct cmCommandLineArgument
- {
- enum class Values
- {
- Zero,
- One,
- Two,
- };
- std::string InvalidSyntaxMessage;
- std::string InvalidValueMessage;
- std::string Name;
- Values Type;
- std::function<FunctionSignature> StoreCall;
- template <typename FunctionType>
- cmCommandLineArgument(std::string n, Values t, FunctionType&& func)
- : InvalidSyntaxMessage(cmStrCat("Invalid syntax used with ", n))
- , InvalidValueMessage(cmStrCat("Invalid value used with ", n))
- , Name(std::move(n))
- , Type(t)
- , StoreCall(std::forward<FunctionType>(func))
- {
- }
- template <typename FunctionType>
- cmCommandLineArgument(std::string n, std::string failedMsg, Values t,
- FunctionType&& func)
- : InvalidSyntaxMessage(cmStrCat("Invalid syntax used with ", n))
- , InvalidValueMessage(std::move(failedMsg))
- , Name(std::move(n))
- , Type(t)
- , StoreCall(std::forward<FunctionType>(func))
- {
- }
- bool matches(std::string const& input) const
- {
- return (this->Type == Values::Zero) ? (input == this->Name)
- : cmHasPrefix(input, this->Name);
- }
- template <typename T, typename... CallState>
- bool parse(std::string const& input, T& index,
- std::vector<std::string> const& allArgs,
- CallState&&... state) const
- {
- enum class ParseMode
- {
- Valid,
- Invalid,
- SyntaxError,
- ValueError
- };
- ParseMode parseState = ParseMode::Valid;
- if (this->Type == Values::Zero) {
- if (input.size() == this->Name.size()) {
- parseState =
- this->StoreCall(std::string{}, std::forward<CallState>(state)...)
- ? ParseMode::Valid
- : ParseMode::Invalid;
- } else {
- parseState = ParseMode::SyntaxError;
- }
- } else if (this->Type == Values::One) {
- if (input.size() == this->Name.size()) {
- ++index;
- if (index >= allArgs.size() || allArgs[index][0] == '-') {
- parseState = ParseMode::ValueError;
- } else {
- parseState =
- this->StoreCall(allArgs[index], std::forward<CallState>(state)...)
- ? ParseMode::Valid
- : ParseMode::Invalid;
- }
- } else {
- // parse the string to get the value
- auto possible_value = cm::string_view(input).substr(this->Name.size());
- if (possible_value.empty()) {
- parseState = ParseMode::SyntaxError;
- parseState = ParseMode::ValueError;
- } else if (possible_value[0] == '=') {
- possible_value.remove_prefix(1);
- if (possible_value.empty()) {
- parseState = ParseMode::ValueError;
- } else {
- parseState = this->StoreCall(std::string(possible_value),
- std::forward<CallState>(state)...)
- ? ParseMode::Valid
- : ParseMode::Invalid;
- }
- }
- if (parseState == ParseMode::Valid) {
- parseState = this->StoreCall(std::string(possible_value),
- std::forward<CallState>(state)...)
- ? ParseMode::Valid
- : ParseMode::Invalid;
- }
- }
- } else if (this->Type == Values::Two) {
- if (input.size() == this->Name.size()) {
- if (index + 2 >= allArgs.size() || allArgs[index + 1][0] == '-' ||
- allArgs[index + 2][0] == '-') {
- parseState = ParseMode::ValueError;
- } else {
- index += 2;
- parseState =
- this->StoreCall(cmStrCat(allArgs[index - 1], ";", allArgs[index]),
- std::forward<CallState>(state)...)
- ? ParseMode::Valid
- : ParseMode::Invalid;
- }
- }
- }
- if (parseState == ParseMode::SyntaxError) {
- cmSystemTools::Error(this->InvalidSyntaxMessage);
- } else if (parseState == ParseMode::ValueError) {
- cmSystemTools::Error(this->InvalidValueMessage);
- }
- return (parseState == ParseMode::Valid);
- }
- };
|