You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

flag_parser.cc 6.1 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /**
  2. * Copyright 2020 Huawei Technologies Co., Ltd
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "tools/common/flag_parser.h"
  17. #include "src/common/log_adapter.h"
  18. namespace mindspore {
  19. namespace lite {
  20. // parse flags read from command line
  21. Option<std::string> FlagParser::ParseFlags(int argc, const char *const *argv, bool supportUnknown,
  22. bool supportDuplicate) {
  23. MS_ASSERT(argv != nullptr);
  24. const int FLAG_PREFIX_LEN = 2;
  25. // Get binary name
  26. binName = GetFileName(argv[0]);
  27. std::multimap<std::string, Option<std::string>> keyValues;
  28. for (int i = 1; i < argc; i++) {
  29. std::string tmp = argv[i];
  30. Trim(&tmp);
  31. const std::string flagItem(tmp);
  32. if (flagItem == "--") {
  33. break;
  34. }
  35. if (flagItem.find("--") == std::string::npos) {
  36. return Option<std::string>("Failed: flag " + flagItem + " is not valid.");
  37. }
  38. std::string key;
  39. Option<std::string> value = Option<std::string>(None());
  40. size_t pos = flagItem.find_first_of('=');
  41. if (pos == std::string::npos && flagItem.find("--no-") != std::string::npos) {
  42. key = flagItem.substr(FLAG_PREFIX_LEN);
  43. } else if (pos == std::string::npos) {
  44. key = flagItem.substr(FLAG_PREFIX_LEN);
  45. } else {
  46. key = flagItem.substr(FLAG_PREFIX_LEN, pos - FLAG_PREFIX_LEN);
  47. value = Option<std::string>(flagItem.substr(pos + 1));
  48. }
  49. keyValues.insert(std::pair<std::string, Option<std::string>>(key, value));
  50. }
  51. Option<std::string> ret = Option<std::string>(InnerParseFlags(&keyValues));
  52. if (ret.IsSome()) {
  53. return Option<std::string>(ret.Get());
  54. }
  55. return Option<std::string>(None());
  56. }
  57. bool FlagParser::GetRealFlagName(std::string *flagName, const std::string &oriFlagName) {
  58. MS_ASSERT(flagName != nullptr);
  59. const int BOOL_TYPE_FLAG_PREFIX_LEN = 3;
  60. bool opaque = false;
  61. if (StartsWithPrefix(oriFlagName, "no-")) {
  62. *flagName = oriFlagName.substr(BOOL_TYPE_FLAG_PREFIX_LEN);
  63. opaque = true;
  64. } else {
  65. *flagName = oriFlagName;
  66. }
  67. return opaque;
  68. }
  69. // Inner parse function
  70. Option<std::string> FlagParser::InnerParseFlags(std::multimap<std::string, Option<std::string>> *keyValues) {
  71. MS_ASSERT(keyValues != nullptr);
  72. for (auto it = keyValues->begin(); it != keyValues->end(); ++it) {
  73. std::string flagName;
  74. bool opaque = GetRealFlagName(&flagName, (*it).first);
  75. Option<std::string> flagValue = (*it).second;
  76. auto item = flags.find(flagName);
  77. if (item == flags.end()) {
  78. return Option<std::string>(std::string(flagName + " is not a valid flag"));
  79. }
  80. FlagInfo *flag = &(item->second);
  81. if (flag == nullptr) {
  82. return Option<std::string>("Failed: flag is nullptr");
  83. }
  84. if (flag->isParsed) {
  85. return Option<std::string>("Failed: already parsed flag: " + flagName);
  86. }
  87. std::string tmpValue;
  88. if (!flag->isBoolean) {
  89. if (opaque) {
  90. return Option<std::string>(flagName + " is not a boolean type");
  91. }
  92. if (flagValue.IsNone()) {
  93. return Option<std::string>("No value provided for non-boolean type: " + flagName);
  94. }
  95. tmpValue = flagValue.Get();
  96. } else {
  97. if (flagValue.IsNone() || flagValue.Get().empty()) {
  98. tmpValue = !opaque ? "true" : "false";
  99. } else if (!opaque) {
  100. tmpValue = flagValue.Get();
  101. } else {
  102. return Option<std::string>(std::string("Boolean flag can not have non-empty value"));
  103. }
  104. }
  105. // begin to parse value
  106. Option<Nothing> ret = flag->parse(this, tmpValue);
  107. if (ret.IsNone()) {
  108. return Option<std::string>("Failed to parse value for: " + flag->flagName);
  109. }
  110. flag->isParsed = true;
  111. }
  112. // to check flags not given in command line but added as in constructor
  113. for (auto &flag : flags) {
  114. if (flag.second.isRequired && !flag.second.isParsed) {
  115. return Option<std::string>("Error, value of '" + flag.first + "' not provided");
  116. }
  117. }
  118. return Option<std::string>(None());
  119. }
  120. void Replaceall(std::string *str, const std::string &oldValue, const std::string &newValue) {
  121. if (str == nullptr) {
  122. MS_LOG(ERROR) << "Input str is nullptr";
  123. return;
  124. }
  125. while (true) {
  126. std::string::size_type pos(0);
  127. if ((pos = str->find(oldValue)) != std::string::npos) {
  128. str->replace(pos, oldValue.length(), newValue);
  129. } else {
  130. break;
  131. }
  132. }
  133. }
  134. std::string FlagParser::Usage(const Option<std::string> &usgMsg) const {
  135. // first line, brief of the usage
  136. std::string usageString = usgMsg.IsSome() ? usgMsg.Get() + "\n" : "";
  137. // usage of bin name
  138. usageString += usageMsg.IsNone() ? "usage: " + binName + " [options]\n" : usageMsg.Get() + "\n";
  139. // help line of help message, usageLine:message of parametors
  140. std::string helpLine = "";
  141. std::string usageLine = "";
  142. uint32_t i = 0;
  143. for (auto flag = flags.begin(); flag != flags.end(); flag++) {
  144. std::string flagName = flag->second.flagName;
  145. std::string helpInfo = flag->second.helpInfo;
  146. // parameter line
  147. std::string thisLine = flagName == "help" ? " --" + flagName : " --" + flagName + "=VALUE";
  148. if (++i <= flags.size()) {
  149. // add parameter help message of each line
  150. thisLine += " " + helpInfo;
  151. Replaceall(&helpInfo, "\n\r", "\n");
  152. usageLine += thisLine + "\n";
  153. } else {
  154. // breif help message
  155. helpLine = thisLine + " " + helpInfo + "\n";
  156. }
  157. }
  158. // total usage is brief of usage+ brief of bin + help message + brief of
  159. // parameters
  160. return usageString + helpLine + usageLine;
  161. }
  162. } // namespace lite
  163. } // namespace mindspore