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.h 9.0 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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. #ifndef PREDICT_COMMON_FLAG_PARSER_H_
  17. #define PREDICT_COMMON_FLAG_PARSER_H_
  18. #include <functional>
  19. #include <map>
  20. #include <utility>
  21. #include <string>
  22. #include "src/common/utils.h"
  23. #include "tools/common/option.h"
  24. namespace mindspore {
  25. namespace lite {
  26. struct FlagInfo;
  27. struct Nothing {};
  28. class FlagParser {
  29. public:
  30. FlagParser() { AddFlag(&FlagParser::help, "help", "print usage message", ""); }
  31. virtual ~FlagParser() {}
  32. // only support read flags from command line
  33. virtual Option<std::string> ParseFlags(int argc, const char *const *argv, bool supportUnknown = false,
  34. bool supportDuplicate = false);
  35. std::string Usage(const Option<std::string> &usgMsg = Option<std::string>(None())) const;
  36. template <typename Flags, typename T1, typename T2>
  37. void AddFlag(T1 *t1, const std::string &flagName, const std::string &helpInfo, const T2 *t2);
  38. template <typename Flags, typename T1, typename T2>
  39. void AddFlag(T1 *t1, const std::string &flagName, const std::string &helpInfo, const T2 &t2);
  40. // non-Option type fields in class
  41. template <typename Flags, typename T1, typename T2>
  42. void AddFlag(T1 Flags::*t1, const std::string &flagName, const std::string &helpInfo, const T2 *t2);
  43. template <typename Flags, typename T1, typename T2>
  44. void AddFlag(T1 Flags::*t1, const std::string &flagName, const std::string &helpInfo, const T2 &t2);
  45. template <typename Flags, typename T>
  46. void AddFlag(T Flags::*t, const std::string &flagName, const std::string &helpInfo);
  47. // Option-type fields
  48. template <typename Flags, typename T>
  49. void AddFlag(Option<T> Flags::*t, const std::string &flagName, const std::string &helpInfo);
  50. bool help;
  51. protected:
  52. template <typename Flags>
  53. void AddFlag(std::string Flags::*t1, const std::string &flagName, const std::string &helpInfo, const char *t2) {
  54. AddFlag(t1, flagName, helpInfo, std::string(t2));
  55. }
  56. std::string binName;
  57. Option<std::string> usageMsg;
  58. private:
  59. struct FlagInfo {
  60. std::string flagName;
  61. bool isRequired;
  62. bool isBoolean;
  63. std::string helpInfo;
  64. bool isParsed;
  65. std::function<Option<Nothing>(FlagParser *, const std::string &)> parse;
  66. };
  67. inline void AddFlag(const FlagInfo &flag);
  68. // construct a temporary flag
  69. template <typename Flags, typename T>
  70. void ConstructFlag(Option<T> Flags::*t, const std::string &flagName, const std::string &helpInfo, FlagInfo *flag);
  71. // construct a temporary flag
  72. template <typename Flags, typename T1>
  73. void ConstructFlag(T1 Flags::*t1, const std::string &flagName, const std::string &helpInfo, FlagInfo *flag);
  74. Option<std::string> InnerParseFlags(std::multimap<std::string, Option<std::string>> *values);
  75. bool GetRealFlagName(std::string *flagName, const std::string &oriFlagName);
  76. std::map<std::string, FlagInfo> flags;
  77. };
  78. // convert to std::string
  79. template <typename Flags, typename T>
  80. Option<std::string> ConvertToString(T Flags::*t, const FlagParser &baseFlag) {
  81. const Flags *flag = dynamic_cast<Flags *>(&baseFlag);
  82. if (flag != nullptr) {
  83. return std::to_string(flag->*t);
  84. }
  85. return Option<std::string>(None());
  86. }
  87. // construct for a Option-type flag
  88. template <typename Flags, typename T>
  89. void FlagParser::ConstructFlag(Option<T> Flags::*t1, const std::string &flagName, const std::string &helpInfo,
  90. FlagInfo *flag) {
  91. if (flag == nullptr) {
  92. // MS_LOGE("FlagInfo is nullptr");
  93. return;
  94. }
  95. flag->flagName = flagName;
  96. flag->helpInfo = helpInfo;
  97. flag->isBoolean = typeid(T) == typeid(bool);
  98. flag->isParsed = false;
  99. }
  100. // construct a temporary flag
  101. template <typename Flags, typename T>
  102. void FlagParser::ConstructFlag(T Flags::*t1, const std::string &flagName, const std::string &helpInfo, FlagInfo *flag) {
  103. if (flag == nullptr) {
  104. // MS_LOGE("FlagInfo is nullptr");
  105. return;
  106. }
  107. if (t1 == nullptr) {
  108. // MS_LOGE("t1 is nullptr");
  109. return;
  110. }
  111. flag->flagName = flagName;
  112. flag->helpInfo = helpInfo;
  113. flag->isBoolean = typeid(T) == typeid(bool);
  114. flag->isParsed = false;
  115. }
  116. inline void FlagParser::AddFlag(const FlagInfo &flagItem) { flags[flagItem.flagName] = flagItem; }
  117. template <typename Flags, typename T>
  118. void FlagParser::AddFlag(T Flags::*t, const std::string &flagName, const std::string &helpInfo) {
  119. if (t == nullptr) {
  120. // MS_LOGE("t1 is nullptr");
  121. return;
  122. }
  123. AddFlag(t, flagName, helpInfo, static_cast<const T *>(nullptr));
  124. }
  125. template <typename Flags, typename T1, typename T2>
  126. void FlagParser::AddFlag(T1 Flags::*t1, const std::string &flagName, const std::string &helpInfo, const T2 &t2) {
  127. if (t1 == nullptr) {
  128. // MS_LOGE("t1 is nullptr");
  129. return;
  130. }
  131. AddFlag(t1, flagName, helpInfo, &t2);
  132. }
  133. // just for test
  134. template <typename Flags, typename T1, typename T2>
  135. void AddFlag(T1 *t1, const std::string &flagName, const std::string &helpInfo, const T2 &t2) {
  136. if (t1 == nullptr) {
  137. // MS_LOGE("t1 is nullptr");
  138. return;
  139. }
  140. AddFlag(t1, flagName, helpInfo, &t2);
  141. }
  142. template <typename Flags, typename T1, typename T2>
  143. void FlagParser::AddFlag(T1 *t1, const std::string &flagName, const std::string &helpInfo, const T2 *t2) {
  144. if (t1 == nullptr) {
  145. // MS_LOGE("t1 is nullptr");
  146. return;
  147. }
  148. FlagInfo flagItem;
  149. // flagItem is as a output parameter
  150. ConstructFlag(t1, flagName, helpInfo, flagItem);
  151. flagItem.parse = [t1](FlagParser *base, const std::string &value) -> Option<Nothing> {
  152. if (base != nullptr) {
  153. Option<T1> ret = Option<T1>(GenericParseValue<T1>(value));
  154. if (ret.IsNone()) {
  155. return Option<T1>(None());
  156. } else {
  157. *t1 = ret.Get();
  158. }
  159. }
  160. return Option<Nothing>(Nothing());
  161. };
  162. if (t2 != nullptr) {
  163. flagItem.isRequired = false;
  164. *t1 = *t2;
  165. }
  166. flagItem.helpInfo +=
  167. !helpInfo.empty() && helpInfo.find_last_of("\n\r") != helpInfo.size() - 1 ? " (default: " : "(default: ";
  168. if (t2 != nullptr) {
  169. flagItem.helpInfo += ToString(*t2).Get();
  170. }
  171. flagItem.helpInfo += ")";
  172. // add this flag to a std::map
  173. AddFlag(flagItem);
  174. }
  175. template <typename Flags, typename T1, typename T2>
  176. void FlagParser::AddFlag(T1 Flags::*t1, const std::string &flagName, const std::string &helpInfo, const T2 *t2) {
  177. if (t1 == nullptr) {
  178. // MS_LOGE("t1 is nullptr");
  179. return;
  180. }
  181. Flags *flag = dynamic_cast<Flags *>(this);
  182. if (flag == nullptr) {
  183. return;
  184. }
  185. FlagInfo flagItem;
  186. // flagItem is as a output parameter
  187. ConstructFlag(t1, flagName, helpInfo, &flagItem);
  188. flagItem.parse = [t1](FlagParser *base, const std::string &value) -> Option<Nothing> {
  189. Flags *flag = dynamic_cast<Flags *>(base);
  190. if (base != nullptr) {
  191. Option<T1> ret = Option<T1>(GenericParseValue<T1>(value));
  192. if (ret.IsNone()) {
  193. return Option<Nothing>(None());
  194. } else {
  195. flag->*t1 = ret.Get();
  196. }
  197. }
  198. return Option<Nothing>(Nothing());
  199. };
  200. if (t2 != nullptr) {
  201. flagItem.isRequired = false;
  202. flag->*t1 = *t2;
  203. } else {
  204. flagItem.isRequired = true;
  205. }
  206. flagItem.helpInfo +=
  207. !helpInfo.empty() && helpInfo.find_last_of("\n\r") != helpInfo.size() - 1 ? " (default: " : "(default: ";
  208. if (t2 != nullptr) {
  209. flagItem.helpInfo += ToString(*t2).Get();
  210. }
  211. flagItem.helpInfo += ")";
  212. // add this flag to a std::map
  213. AddFlag(flagItem);
  214. }
  215. // option-type add flag
  216. template <typename Flags, typename T>
  217. void FlagParser::AddFlag(Option<T> Flags::*t, const std::string &flagName, const std::string &helpInfo) {
  218. if (t == nullptr) {
  219. // MS_LOGE("t is nullptr");
  220. return;
  221. }
  222. Flags *flag = dynamic_cast<Flags *>(this);
  223. if (flag == nullptr) {
  224. // MS_LOGE("dynamic_cast failed");
  225. return;
  226. }
  227. FlagInfo flagItem;
  228. // flagItem is as a output parameter
  229. ConstructFlag(t, flagName, helpInfo, &flagItem);
  230. flagItem.isRequired = false;
  231. flagItem.parse = [t](FlagParser *base, const std::string &value) -> Option<Nothing> {
  232. Flags *flag = dynamic_cast<Flags *>(base);
  233. if (base != nullptr) {
  234. Option<T> ret = Option<std::string>(GenericParseValue<T>(value));
  235. if (ret.IsNone()) {
  236. return Option<Nothing>(None());
  237. } else {
  238. flag->*t = Option<T>(Some(ret.Get()));
  239. }
  240. }
  241. return Option<Nothing>(Nothing());
  242. };
  243. // add this flag to a std::map
  244. AddFlag(flagItem);
  245. }
  246. } // namespace lite
  247. } // namespace mindspore
  248. #endif // PREDICT_COMMON_FLAG_PARSER_H_