cnstream_param.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. /*************************************************************************
  2. * Copyright (C) [2021] by Cambricon, Inc. All rights reserved
  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. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  13. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  14. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  15. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  16. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  17. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  18. * THE SOFTWARE.
  19. *************************************************************************/
  20. #ifndef CNSTREAM_PARAM_HPP_
  21. #define CNSTREAM_PARAM_HPP_
  22. /**
  23. * \file cnstream_param.hpp
  24. *
  25. * This file is for module parameter registration , parsing and checking.
  26. */
  27. #include <algorithm>
  28. #include <atomic>
  29. #include <functional>
  30. #include <memory>
  31. #include <sstream>
  32. #include <string>
  33. #include <unordered_map>
  34. #include <vector>
  35. #include "cnstream_config.hpp"
  36. #include "cnstream_logging.hpp"
  37. #define OFFSET(S, M) (size_t) & (((S*)0)->M) // NOLINT
  38. #define PARAM_OPTIONAL 0
  39. #define PARAM_REQUIRED 1
  40. #define PARAM_DEPRECATED 2
  41. namespace cnstream {
  42. /**
  43. * @struct ModuleParamDesc
  44. *
  45. * @brief The ModuleParamDesc is a structure describing a parameter.
  46. */
  47. typedef struct ModuleParamDesc {
  48. std::string name; /*!< The name of this parameter. */
  49. std::string default_value; /*!< The default value of this parameter. */
  50. std::string str_desc; /*!< The description of this parameter. */
  51. int optional; /*!< Does the user have to set this parameter. */
  52. int offset; /*!< This Parameter offset relative to structure. */
  53. std::function<bool(const ModuleParamSet&, const std::string&, const std::string&, void*)>
  54. parser; /*!< How to parse this parameter. */
  55. std::string type; /*!< This Parameter`s type . */
  56. } ModuleParamDesc;
  57. /**
  58. * @class ModuleParamParser
  59. *
  60. * @brief Some built-in parameter parse functions.
  61. *
  62. * @param[in] T Parameter type。
  63. */
  64. template <typename T>
  65. class ModuleParamParser {
  66. public:
  67. static bool Parser(const ModuleParamSet& param_set, const std::string& param_name, const std::string& str,
  68. void* result) {
  69. try {
  70. std::istringstream ss(str);
  71. ss >> *static_cast<T*>(result);
  72. return true;
  73. } catch (const std::exception& e) {
  74. std::cerr << e.what() << '\n';
  75. }
  76. return false;
  77. }
  78. static bool VectorParser(const ModuleParamSet& param_set, const std::string& param_name, const std::string& str,
  79. void* result) {
  80. std::vector<std::string> strs = cnstream::StringSplit(str, ',');
  81. std::vector<T> values;
  82. try {
  83. for (auto& s : strs) {
  84. T value;
  85. std::istringstream ss(s);
  86. ss >> *static_cast<T*>(&value);
  87. values.push_back(value);
  88. }
  89. *static_cast<std::vector<T>*>(result) = values;
  90. return true;
  91. } catch (const std::exception& e) {
  92. std::cerr << e.what() << '\n';
  93. }
  94. return false;
  95. }
  96. };
  97. template <>
  98. class ModuleParamParser<int> {
  99. public:
  100. static bool Parser(const ModuleParamSet& param_set, const std::string& param_name, const std::string& str,
  101. void* result) {
  102. std::string not_const_str = str;
  103. std::remove_if(not_const_str.begin(), not_const_str.end(), ::isblank);
  104. try {
  105. *static_cast<int*>(result) = std::stoi(not_const_str);
  106. return true;
  107. } catch (const std::exception& e) {
  108. LOGE(CORE) << "[ModuleParamParser] : Int Parser wrong param : " << param_name << ": " << not_const_str;
  109. }
  110. return false;
  111. }
  112. };
  113. template <>
  114. class ModuleParamParser<float> {
  115. public:
  116. static bool Parser(const ModuleParamSet& param_set, const std::string& param_name, const std::string& str,
  117. void* result) {
  118. std::string not_const_str = str;
  119. std::remove_if(not_const_str.begin(), not_const_str.end(), ::isblank);
  120. try {
  121. *static_cast<float*>(result) = std::stof(not_const_str);
  122. return true;
  123. } catch (const std::exception& e) {
  124. LOGE(CORE) << "[ModuleParamParser] : Float Parser wrong param : " << param_name << ": " << not_const_str;
  125. }
  126. return false;
  127. }
  128. };
  129. template <>
  130. class ModuleParamParser<double> {
  131. public:
  132. static bool Parser(const ModuleParamSet& param_set, const std::string& param_name, const std::string& str,
  133. void* result) {
  134. std::string not_const_str = str;
  135. std::remove_if(not_const_str.begin(), not_const_str.end(), ::isblank);
  136. try {
  137. *static_cast<double*>(result) = std::stod(not_const_str);
  138. return true;
  139. } catch (const std::exception& e) {
  140. LOGE(CORE) << "[ModuleParamParser] : Double Parser wrong param : " << param_name << ": " << not_const_str;
  141. }
  142. return false;
  143. }
  144. };
  145. template <>
  146. class ModuleParamParser<bool> {
  147. public:
  148. static bool Parser(const ModuleParamSet& param_set, const std::string& param_name, const std::string& str,
  149. void* result) {
  150. static std::vector<std::string> true_vec = {"True", "TRUE", "true", "1"};
  151. static std::vector<std::string> false_vec = {"False", "FALSE", "false", "0"};
  152. std::string not_const_str = str;
  153. std::remove_if(not_const_str.begin(), not_const_str.end(), ::isblank);
  154. for (auto& it : true_vec) {
  155. if (it == not_const_str) {
  156. *static_cast<bool*>(result) = true;
  157. return true;
  158. }
  159. }
  160. for (auto& it : false_vec) {
  161. if (it == not_const_str) {
  162. *static_cast<bool*>(result) = false;
  163. return true;
  164. }
  165. }
  166. LOGE(CORE) << "[ModuleParamParser] : Bool Parser wrong param : " << param_name << ": " << not_const_str;
  167. return false;
  168. }
  169. };
  170. /**
  171. * @class ModuleParamsHelper
  172. *
  173. * @brief ModuleParamsHelper used to manage module parameters.
  174. *
  175. * @param[in] T Structure that module`s parameters.
  176. */
  177. template <class T>
  178. class ModuleParamsHelper {
  179. public:
  180. /**
  181. * @brief A constructor to construct one module parameters helper.
  182. *
  183. * @param[in] name The name of the module parameters helper.
  184. *
  185. * @return None.
  186. */
  187. explicit ModuleParamsHelper(const std::string& name) : module_name_(name) {}
  188. ModuleParamsHelper(const ModuleParamsHelper&) = delete;
  189. ModuleParamsHelper& operator=(const ModuleParamsHelper&) = delete;
  190. /**
  191. * @brief Gets the module's parameters.
  192. *
  193. * @param None.
  194. *
  195. * @return Returns the module's parameters.
  196. */
  197. const T& GetParams() const noexcept {
  198. if (!init_) {
  199. LOGW(CORE) << "module param not init.";
  200. }
  201. return params_;
  202. }
  203. /**
  204. * @brief Register a series of parameters.
  205. *
  206. * @param[in] params_desc A series description of parameters.
  207. *
  208. * @return Returns true if parameters have register successfully. Returns false if parameters
  209. * register failed.
  210. */
  211. bool Register(const std::vector<ModuleParamDesc>& params_desc, ParamRegister* param_register = nullptr) {
  212. if (param_register) {
  213. param_register_ = param_register;
  214. }
  215. for (auto& it : params_desc) {
  216. if (!Register(it)) {
  217. LOGE(CORE) << "Parameter [ " << it.name << " ] Register failed. ";
  218. return false;
  219. }
  220. }
  221. return true;
  222. }
  223. /**
  224. * @brief Register a parameter.
  225. *
  226. * @param[in] params_desc A description of parameter.
  227. *
  228. * @return Returns true if parameter has register successfully. Returns false if parameter
  229. * register failed.
  230. */
  231. bool Register(const ModuleParamDesc& param_desc, ParamRegister* param_register = nullptr) {
  232. if (param_register) {
  233. param_register_ = param_register;
  234. }
  235. std::shared_ptr<ModuleParamDesc> p_desc = std::make_shared<ModuleParamDesc>();
  236. std::string name = param_desc.name;
  237. std::remove_if(name.begin(), name.end(), ::isblank);
  238. p_desc->name = name;
  239. if ("" == p_desc->name) {
  240. LOGE(CORE) << "[ModuleParam] : empty parameter name, register failed.";
  241. return false;
  242. }
  243. p_desc->default_value = param_desc.default_value;
  244. p_desc->optional = param_desc.optional;
  245. if (p_desc->optional != PARAM_DEPRECATED) {
  246. p_desc->offset = param_desc.offset;
  247. p_desc->type = param_desc.type;
  248. if (nullptr == param_desc.parser) {
  249. LOGE(CORE) << "[ModuleParam] : register " << param_desc.name << " failed, "
  250. << " you should set default parser or custom parser";
  251. return false;
  252. } else {
  253. p_desc->parser = param_desc.parser;
  254. }
  255. }
  256. p_desc->str_desc = param_desc.str_desc;
  257. params_desc_[name] = p_desc;
  258. if (param_register_ && p_desc->optional != PARAM_DEPRECATED) {
  259. IRegisterParam(*p_desc.get());
  260. }
  261. registered_ = true;
  262. return true;
  263. }
  264. /**
  265. * @brief Parse parameters.
  266. *
  267. * @param[in] params A map contains parameter names and user set parameter values.
  268. *
  269. * @return Returns true if parameters have parse successfully. Returns false if parameters
  270. * parse failed.
  271. */
  272. bool ParseParams(const std::unordered_map<std::string, std::string>& params) {
  273. if (!registered_) {
  274. LOGE(CORE) << "[ModuleParam] : register failed, ";
  275. return false;
  276. }
  277. std::unordered_map<std::string, std::string> map = params;
  278. for (auto& it : params_desc_) {
  279. if (it.second->optional == PARAM_DEPRECATED) {
  280. continue;
  281. }
  282. auto iter = map.find(it.first);
  283. if (map.end() == iter && it.second->optional == PARAM_REQUIRED) {
  284. LOGE(CORE) << "[ModuleParam]:not find " << it.first << " , parser failed, "
  285. << "you must set this parameter!";
  286. return false;
  287. }
  288. std::string str_value;
  289. std::string str_param = it.first;
  290. if (it.second->optional == PARAM_OPTIONAL && map.end() == iter) {
  291. str_value = it.second->default_value;
  292. } else {
  293. str_value = iter->second;
  294. }
  295. if (!it.second->parser(params, str_param, str_value, ((char*)&params_ + it.second->offset))) { // NOLINT
  296. LOGE(CORE) << "[MOduleParam]: parse parameter failed. param: " << str_param << " val: " << str_value;
  297. return false;
  298. }
  299. }
  300. for (auto& it : params_desc_) {
  301. auto iter = map.find(it.first);
  302. if (iter != map.end()) {
  303. if (it.second->optional == PARAM_DEPRECATED) {
  304. LOGW(CORE) << "[ModuleParam]: " << it.first << " is a deprecated parameter. " << it.second->str_desc;
  305. }
  306. map.erase(it.first);
  307. }
  308. }
  309. bool flag = true;
  310. for (auto& it : map) {
  311. if (CNS_JSON_DIR_PARAM_NAME != it.first) {
  312. LOGE(CORE) << "[ModuleParam]: not registed this param:[" << it.first << "]:[" << it.second << "]";
  313. flag = false;
  314. }
  315. }
  316. init_ = true;
  317. return flag;
  318. }
  319. void SetRegister(ParamRegister *param_register) {
  320. if (!param_register) {
  321. LOGE(CORE) << "[ModuleParam] set param register failed";
  322. return;
  323. }
  324. param_register_ = param_register;
  325. }
  326. bool IRegisterParam(const ModuleParamDesc &param_desc) {
  327. if (param_register_) {
  328. std::string desc = param_desc.str_desc + " --- "
  329. + "type : [" + param_desc.type + "] --- "
  330. + "default value : [" + param_desc.default_value + "]";
  331. param_register_->Register(param_desc.name, desc);
  332. return true;
  333. }
  334. LOGE(CORE) << "you should call SetRegister before registing parameters.";
  335. return false;
  336. }
  337. private:
  338. std::atomic<bool> init_{false};
  339. std::atomic<bool> registered_{false};
  340. std::string module_name_;
  341. using ParamsDesc = std::unordered_map<std::string, std::shared_ptr<ModuleParamDesc>>;
  342. ParamsDesc params_desc_;
  343. T params_;
  344. ParamRegister *param_register_ = nullptr;
  345. }; // class ModuleParamHelper
  346. } // namespace cnstream
  347. #endif // !CNSTREAM_PARAM_HPP_