cmCommandLineArgument.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #pragma once
  4. #include "cmStringAlgorithms.h"
  5. #include "cmSystemTools.h"
  6. template <typename FunctionSignature>
  7. struct cmCommandLineArgument
  8. {
  9. enum class Values
  10. {
  11. Zero,
  12. One,
  13. Two,
  14. };
  15. std::string InvalidSyntaxMessage;
  16. std::string InvalidValueMessage;
  17. std::string Name;
  18. Values Type;
  19. std::function<FunctionSignature> StoreCall;
  20. template <typename FunctionType>
  21. cmCommandLineArgument(std::string n, Values t, FunctionType&& func)
  22. : InvalidSyntaxMessage(cmStrCat("Invalid syntax used with ", n))
  23. , InvalidValueMessage(cmStrCat("Invalid value used with ", n))
  24. , Name(std::move(n))
  25. , Type(t)
  26. , StoreCall(std::forward<FunctionType>(func))
  27. {
  28. }
  29. template <typename FunctionType>
  30. cmCommandLineArgument(std::string n, std::string failedMsg, Values t,
  31. FunctionType&& func)
  32. : InvalidSyntaxMessage(cmStrCat("Invalid syntax used with ", n))
  33. , InvalidValueMessage(std::move(failedMsg))
  34. , Name(std::move(n))
  35. , Type(t)
  36. , StoreCall(std::forward<FunctionType>(func))
  37. {
  38. }
  39. bool matches(std::string const& input) const
  40. {
  41. return (this->Type == Values::Zero) ? (input == this->Name)
  42. : cmHasPrefix(input, this->Name);
  43. }
  44. template <typename T, typename... CallState>
  45. bool parse(std::string const& input, T& index,
  46. std::vector<std::string> const& allArgs,
  47. CallState&&... state) const
  48. {
  49. enum class ParseMode
  50. {
  51. Valid,
  52. Invalid,
  53. SyntaxError,
  54. ValueError
  55. };
  56. ParseMode parseState = ParseMode::Valid;
  57. if (this->Type == Values::Zero) {
  58. if (input.size() == this->Name.size()) {
  59. parseState =
  60. this->StoreCall(std::string{}, std::forward<CallState>(state)...)
  61. ? ParseMode::Valid
  62. : ParseMode::Invalid;
  63. } else {
  64. parseState = ParseMode::SyntaxError;
  65. }
  66. } else if (this->Type == Values::One) {
  67. if (input.size() == this->Name.size()) {
  68. ++index;
  69. if (index >= allArgs.size() || allArgs[index][0] == '-') {
  70. parseState = ParseMode::ValueError;
  71. } else {
  72. parseState =
  73. this->StoreCall(allArgs[index], std::forward<CallState>(state)...)
  74. ? ParseMode::Valid
  75. : ParseMode::Invalid;
  76. }
  77. } else {
  78. // parse the string to get the value
  79. auto possible_value = cm::string_view(input).substr(this->Name.size());
  80. if (possible_value.empty()) {
  81. parseState = ParseMode::SyntaxError;
  82. parseState = ParseMode::ValueError;
  83. } else if (possible_value[0] == '=') {
  84. possible_value.remove_prefix(1);
  85. if (possible_value.empty()) {
  86. parseState = ParseMode::ValueError;
  87. } else {
  88. parseState = this->StoreCall(std::string(possible_value),
  89. std::forward<CallState>(state)...)
  90. ? ParseMode::Valid
  91. : ParseMode::Invalid;
  92. }
  93. }
  94. if (parseState == ParseMode::Valid) {
  95. parseState = this->StoreCall(std::string(possible_value),
  96. std::forward<CallState>(state)...)
  97. ? ParseMode::Valid
  98. : ParseMode::Invalid;
  99. }
  100. }
  101. } else if (this->Type == Values::Two) {
  102. if (input.size() == this->Name.size()) {
  103. if (index + 2 >= allArgs.size() || allArgs[index + 1][0] == '-' ||
  104. allArgs[index + 2][0] == '-') {
  105. parseState = ParseMode::ValueError;
  106. } else {
  107. index += 2;
  108. parseState =
  109. this->StoreCall(cmStrCat(allArgs[index - 1], ";", allArgs[index]),
  110. std::forward<CallState>(state)...)
  111. ? ParseMode::Valid
  112. : ParseMode::Invalid;
  113. }
  114. }
  115. }
  116. if (parseState == ParseMode::SyntaxError) {
  117. cmSystemTools::Error(this->InvalidSyntaxMessage);
  118. } else if (parseState == ParseMode::ValueError) {
  119. cmSystemTools::Error(this->InvalidValueMessage);
  120. }
  121. return (parseState == ParseMode::Valid);
  122. }
  123. };