diff options
author | Robert Maynard <robert.maynard@kitware.com> | 2020-12-28 21:41:18 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2021-01-06 14:11:14 (GMT) |
commit | 0fb78576b00aa9ca39112210d19ec53b0e6e975c (patch) | |
tree | 5df1efa060f264ed5833bada9197ab202169db47 /Source/cmCommandLineArgument.h | |
parent | 25a1cdef956e0c26067edbef3daa55ec6c65caae (diff) | |
download | CMake-0fb78576b00aa9ca39112210d19ec53b0e6e975c.zip CMake-0fb78576b00aa9ca39112210d19ec53b0e6e975c.tar.gz CMake-0fb78576b00aa9ca39112210d19ec53b0e6e975c.tar.bz2 |
cmake: Use shared parsing code for all cmake argv parsing
Diffstat (limited to 'Source/cmCommandLineArgument.h')
-rw-r--r-- | Source/cmCommandLineArgument.h | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/Source/cmCommandLineArgument.h b/Source/cmCommandLineArgument.h new file mode 100644 index 0000000..aa96305 --- /dev/null +++ b/Source/cmCommandLineArgument.h @@ -0,0 +1,133 @@ +/* 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); + } +}; |