class_view.hpp 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147
  1. #pragma once
  2. #include <iostream>
  3. #include <filesystem>
  4. #include <regex>
  5. #include <map>
  6. #include <any>
  7. #include <variant>
  8. #include <fstream>
  9. #include <chrono>
  10. #include <random>
  11. #include <fmt/format.h>
  12. namespace analysis {
  13. struct class_attribute_info;
  14. /**
  15. * @brief 工具
  16. */
  17. class utils {
  18. public:
  19. /**
  20. * @brief 字符串
  21. */
  22. class string {
  23. public:
  24. /**
  25. * @brief 替换
  26. * @param value
  27. * @param old_str
  28. * @param new_str
  29. * @return
  30. */
  31. static std::string replace(std::string const& value, std::string const& old_str, std::string const& new_str) {
  32. std::string result = value;
  33. for (std::string::size_type pos(0); pos != std::string::npos; pos += new_str.length()) {
  34. pos = result.find(old_str, pos);
  35. if (pos != std::string::npos)
  36. result.replace(pos, old_str.length(), new_str);
  37. else
  38. break;
  39. }
  40. return result;
  41. }
  42. /**
  43. * @brief 分割字符串
  44. * @param value
  45. * @return
  46. */
  47. static std::vector<std::string> split(std::string const& value) {
  48. std::string c = ",";
  49. std::vector<std::string> result;
  50. if (value.empty()) {
  51. return result;
  52. }
  53. std::string strs = value + c;
  54. size_t pos = strs.find(c);
  55. while (pos != strs.npos) {
  56. std::string temp = strs.substr(0, pos);
  57. result.push_back(temp);
  58. strs = strs.substr(pos + c.size(), strs.size());
  59. pos = strs.find(c);
  60. }
  61. return result;
  62. }
  63. /**
  64. * @brief
  65. * @param values
  66. * @return
  67. */
  68. static std::string join(std::vector<std::string> values, std::string c = ",") {
  69. std::string result;
  70. while (!values.empty()) {
  71. if (result.empty()) {
  72. result = values[0];
  73. values.erase(values.begin());
  74. }
  75. else {
  76. result += c + values[0];
  77. values.erase(values.begin());
  78. }
  79. }
  80. return result;
  81. }
  82. /**
  83. * @brief 删除首尾空格
  84. * @param value
  85. * @return
  86. */
  87. static std::string trim(std::string const& value) {
  88. std::string result = value;
  89. while (!result.empty()) {
  90. if (result[0] == ' ' || result[0] == '\t' || result[0] == '\r' || result[0] == '\n')
  91. result.erase(result.begin());
  92. else
  93. break;
  94. }
  95. while (!result.empty()) {
  96. if (result[result.size() - 1] == ' ' || result[result.size() - 1] == '\t' || result[result.size() - 1] == '\r' || result[result.size() - 1] == '\n')
  97. result.pop_back();
  98. else
  99. break;
  100. }
  101. return result;
  102. }
  103. /**
  104. * @brief 大括号
  105. * @param code
  106. * @param index
  107. * @return
  108. */
  109. static bool ergodic(std::string& code, std::size_t& index) {
  110. index++;
  111. for (; index < code.size(); ++index) {
  112. if (code[index] == '}' || code[index] == ')') {
  113. return true;
  114. }
  115. else if (code[index] == '{') {
  116. ergodic(code, index);
  117. }
  118. else if (code[index] == '(') {
  119. ergodic(code, index);
  120. }
  121. else if (code[index] == '"') {
  122. quotation_mark(code, index);
  123. }
  124. }
  125. return false;
  126. }
  127. /**
  128. * @brief 引号
  129. * @param code
  130. * @param index
  131. * @return
  132. */
  133. static bool quotation_mark(std::string& code, std::size_t& index) {
  134. index++;
  135. for (; index < code.size(); ++index) {
  136. if (code[index] == '"') {
  137. return true;
  138. }
  139. }
  140. return false;
  141. }
  142. /**
  143. * @brief
  144. * @return
  145. */
  146. static unsigned int random_char() {
  147. std::random_device rd;
  148. std::mt19937 gen(rd());
  149. std::uniform_int_distribution<> dis(0, 255);
  150. return dis(gen);
  151. }
  152. /**
  153. * @brief
  154. * @param len
  155. * @return
  156. */
  157. static std::string generate_hex(const unsigned int len) {
  158. std::stringstream ss;
  159. for (unsigned int i = 0; i < len; i++) {
  160. const auto rc = random_char();
  161. std::stringstream hexstream;
  162. hexstream << std::hex << rc;
  163. auto hex = hexstream.str();
  164. ss << (hex.length() < 2 ? '0' + hex : hex);
  165. }
  166. return ss.str();
  167. }
  168. /**
  169. * @brief 当前时间
  170. * @return
  171. */
  172. static std::string current_time() {
  173. std::time_t timestamp = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
  174. std::tm now_time;
  175. #ifdef WINDOWS_BUILD
  176. localtime_s(&now_time, &timestamp);
  177. #elif LINUX_BUILD
  178. localtime_r(&timestamp, &now_time);
  179. #endif
  180. std::stringstream ss;
  181. ss << std::put_time(&now_time, "%Y-%m-%d %H:%M:%S");
  182. return ss.str();
  183. }
  184. };
  185. /**
  186. * @brief 正则表达式
  187. */
  188. class regex {
  189. public:
  190. /**
  191. * @brief 特性
  192. * @return
  193. */
  194. static std::regex& attribute() {
  195. static std::regex value("\\[\\[[ \t]{0,30}(ActionType|Method|Authen|Route|ContentType|FileMapping|Json|NoJson|Sql|NoSql|SqlKey|Excel|NoExcel|NoArchive|NoReflect|SqlTable|TemplateType|FromQuery|FromBody|FromHeader|FromUrl|Version|Namespace|Wsdl)[ \t]{0,30}\\([ \t]{0,30}([\\s\\S]*?)[ \t]{0,30}\\)\\]\\]");
  196. return value;
  197. }
  198. /**
  199. * @brief 属性
  200. * @return
  201. */
  202. static std::regex& property() {
  203. static std::regex value("(\\[\\[[\\s\\S]*?\\]\\]|)[ \r\n\t]{0,100}(int|bool|double|float|std::int64_t|v3::datetime|std::string|std::vector<[a-zA-Z_0-9]{1,100}>|[a-zA-Z_0-9]{1,100})[ \t]{1,30}([a-zA-Z_0-9]{1,100})[^;]*;");
  204. return value;
  205. }
  206. /**
  207. * @brief 方法
  208. * @return
  209. */
  210. static std::regex& method() {
  211. static std::regex value("(\\[\\[[\\s\\S]*?\\]\\]|)[ \r\n\t]{0,100}(WebResponse|SoapResponse)[ \r\n\t]{1,30}([a-zA-Z_0-9]{1,100})[ \r\n\t]{0,30}\\(([a-zA-Z0-9\",\\[\\], \r\n\t:<>_\\(\\)]{0,500})\\)");
  212. return value;
  213. }
  214. /**
  215. * @brief 类
  216. * @return
  217. */
  218. static std::regex& class_() {
  219. static std::regex value("(template[ \r\n\t]{0,30}<[\\s\\S]{1,100}>|)[ \r\n\t]{1,30}(struct|class)[ \r\n\t]{1,30}(\\[\\[[\\s\\S]*?\\]\\]|)[ \r\n\t]{0,30}([a-zA-Z_0-9]{1,200})");
  220. return value;
  221. }
  222. /**
  223. * @brief 模板
  224. * @return
  225. */
  226. static std::regex& template_() {
  227. static std::regex value("template[ \r\n\t]{0,30}<([\\s\\S]{1,100})>");
  228. return value;
  229. }
  230. /**
  231. * @brief 参数
  232. * @return
  233. */
  234. static std::regex& parameter() {
  235. static std::regex value("(\\[\\[[ \t]{0,30}(FromQuery|FromBody|FromHeader|FromUrl)[ \t]{0,30}\\([ \t]{0,30}([\\s\\S]*?)[ \t]{0,30}\\)\\]\\]|)[ \r\n\t]{0,100}([a-zA-Z_0-9:<>]{1,100})[ \t\r\n]{1,100}([a-zA-Z_0-9]{1,100})");
  236. return value;
  237. }
  238. };
  239. /**
  240. * @brief 特性
  241. */
  242. class attribute {
  243. public:
  244. //查找
  245. static std::vector<class_attribute_info> find(std::vector<class_attribute_info> const& src, std::string const& attribute);
  246. };
  247. };
  248. struct class_attribute_info {
  249. class_attribute_info() {}
  250. class_attribute_info(std::string code) :
  251. content(code) {
  252. deserialize(code);
  253. }
  254. std::string content;
  255. std::string attribute;
  256. bool bool_value = false;
  257. std::string string_value;
  258. std::vector<std::string> vector_string_value;
  259. std::vector<bool> vector_bool_value;
  260. private:
  261. /**
  262. * @brief
  263. * @param code
  264. */
  265. void deserialize(std::string code) {
  266. std::smatch smatch;
  267. if (std::regex_search(code, smatch, utils::regex::attribute())) {
  268. if (smatch.size() == 3) {
  269. std::vector<std::any> item;
  270. attribute = smatch[1];
  271. get_value(smatch[2]);
  272. }
  273. }
  274. }
  275. /**
  276. * @brief 获取值
  277. * @param code
  278. */
  279. void get_value(std::string code) {
  280. if (code.empty())
  281. return;
  282. auto params = utils::string::split(code);
  283. for (auto it : params) {
  284. it = utils::string::trim(it);
  285. if (attribute == "TemplateType") {
  286. if (it == "false" || it == "true") {
  287. vector_bool_value.push_back(it == "true");
  288. }
  289. else if (it.find('"') != std::string::npos) {
  290. vector_string_value.push_back(it.substr(1, it.size() - 2));
  291. }
  292. }
  293. else {
  294. if (it == "false" || it == "true") {
  295. bool_value = it == "true";
  296. }
  297. else if (it.find('"') != std::string::npos) {
  298. string_value = it.substr(1, it.size() - 2);
  299. }
  300. }
  301. }
  302. }
  303. };
  304. std::vector<class_attribute_info> utils::attribute::find(std::vector<class_attribute_info> const& src, std::string const& attribute) {
  305. std::vector<class_attribute_info> result;
  306. for (auto it : src) {
  307. if (it.attribute == attribute) {
  308. result.push_back(it);
  309. }
  310. }
  311. return result;
  312. }
  313. struct class_property_info {
  314. class_property_info() {}
  315. class_property_info(std::string code) :
  316. content(code) {
  317. deserialize(code);
  318. }
  319. std::string content;
  320. std::string type;
  321. std::string name;
  322. std::vector<class_attribute_info> attributes;
  323. std::string generate_code() {
  324. auto Json = utils::attribute::find(attributes, "Json");
  325. auto Sql = utils::attribute::find(attributes, "Sql");
  326. auto Excel = utils::attribute::find(attributes, "Excel");
  327. auto NoJson = utils::attribute::find(attributes, "NoJson");
  328. auto NoSql = utils::attribute::find(attributes, "NoSql");
  329. auto NoExcel = utils::attribute::find(attributes, "NoExcel");
  330. auto SqlKey = utils::attribute::find(attributes, "SqlKey");
  331. auto NoArchive = utils::attribute::find(attributes, "NoArchive");
  332. return fmt::format("property(\"{}\",&{{0}}::{})(rttr::metadata(\"Json\",\"{}\"),rttr::metadata(\"Sql\",\"{}\"),rttr::metadata(\"Excel\",R\"({})\"),rttr::metadata(\"NoJson\",{}),rttr::metadata(\"NoSql\",{}),rttr::metadata(\"NoExcel\",{}),rttr::metadata(\"SqlKey\",{}),rttr::metadata(\"NoArchive\",{}),rttr::metadata(\"Offset\",robotics::v3::utils::pointer_cast<int>(&{{0}}::{})))",
  333. name,
  334. name,
  335. Json.empty() ? name : Json[0].string_value,
  336. Sql.empty() ? name : Sql[0].string_value,
  337. Excel.empty() ? name : Excel[0].string_value,
  338. NoJson.empty() ? "false" : (NoJson[0].bool_value ? "true" : "false"),
  339. NoSql.empty() ? "false" : (NoSql[0].bool_value ? "true" : "false"),
  340. NoExcel.empty() ? "false" : (NoExcel[0].bool_value ? "true" : "false"),
  341. SqlKey.empty() ? "false" : (SqlKey[0].bool_value ? "true" : "false"),
  342. NoArchive.empty() ? "false" : (NoArchive[0].bool_value ? "true" : "false"),
  343. name);
  344. }
  345. private:
  346. /**
  347. * @brief 反序列化
  348. * @param code
  349. */
  350. void deserialize(std::string code) {
  351. std::smatch smatch;
  352. if (std::regex_search(code, smatch, utils::regex::property())) {
  353. if (smatch.size() == 4) {
  354. type = smatch[2];
  355. name = smatch[3];
  356. for (auto& it : get_attributes(smatch[1])) {
  357. attributes.push_back(class_attribute_info(it));
  358. }
  359. }
  360. }
  361. }
  362. /**
  363. * @brief 获取特性列表
  364. * @param code
  365. * @return
  366. */
  367. std::vector<std::string> get_attributes(std::string code) {
  368. std::vector<std::string> result;
  369. std::smatch smatch;
  370. while (std::regex_search(code, smatch, utils::regex::attribute())) {
  371. if (smatch.size() == 3) {
  372. result.push_back(smatch[0]);
  373. }
  374. code = smatch.suffix();
  375. }
  376. return result;
  377. }
  378. };
  379. struct class_parameter_info {
  380. class_parameter_info() {}
  381. class_parameter_info(std::string code) :
  382. content(code) {
  383. deserialize(code);
  384. }
  385. std::string content;
  386. std::string type;
  387. std::string name;
  388. std::vector<class_attribute_info> attributes;
  389. std::string generate_cntlr_code(std::string const& method_type) {
  390. static std::map<std::string, std::string> type_map = {
  391. {"int", "robotics::v3::mvc::argument_type::Int"},
  392. {"std::int64_t", "robotics::v3::mvc::argument_type::Int64"},
  393. {"float", "robotics::v3::mvc::argument_type::Float"},
  394. {"double", "robotics::v3::mvc::argument_type::Double"},
  395. {"long", "robotics::v3::mvc::argument_type::Long"},
  396. {"bool", "robotics::v3::mvc::argument_type::Bool_"},
  397. {"std::string", "robotics::v3::mvc::argument_type::String"},
  398. {"robotics::v3::datetime", "robotics::v3::mvc::argument_type::DateTime"},
  399. {"v3::datetime", "robotics::v3::mvc::argument_type::DateTime"},
  400. {"datetime", "robotics::v3::mvc::argument_type::DateTime"},
  401. {"std::vector<std::uint8_t>", "robotics::v3::mvc::argument_type::Binary"},
  402. {"std::vector<int>", "robotics::v3::mvc::argument_type::VecInt"},
  403. {"std::vector<std::int64_t>", "robotics::v3::mvc::argument_type::VecInt64"},
  404. {"std::vector<float>", "robotics::v3::mvc::argument_type::VecFloat"},
  405. {"std::vector<double>", "robotics::v3::mvc::argument_type::VecDouble"},
  406. {"std::vector<long>", "robotics::v3::mvc::argument_type::VecLong"},
  407. {"std::vector<bool>", "robotics::v3::mvc::argument_type::VecBool"},
  408. {"std::vector<std::string>", "robotics::v3::mvc::argument_type::VecString"},
  409. {"std::vector<robotics::v3::datetime>", "robotics::v3::mvc::argument_type::VecDateTime"},
  410. {"std::vector<v3::datetime>", "robotics::v3::mvc::argument_type::VecDateTime"},
  411. {"std::vector<datetime>", "robotics::v3::mvc::argument_type::VecDateTime"},
  412. {"VecJson", "robotics::v3::mvc::argument_type::VecJson"},
  413. {"Json", "robotics::v3::mvc::argument_type::Json"},
  414. {"Multipart", "robotics::v3::mvc::argument_type::Multipart"}
  415. };
  416. auto FromQuery = utils::attribute::find(attributes, "FromQuery");
  417. auto FromBody = utils::attribute::find(attributes, "FromBody");
  418. auto FromHeader = utils::attribute::find(attributes, "FromHeader");
  419. auto FromUrl = utils::attribute::find(attributes, "FromUrl");
  420. std::stringstream ss;
  421. ss << "\t\t{" << std::endl;
  422. ss << "\t\t\tstd::shared_ptr<robotics::v3::mvc::action_argument> argument(new robotics::v3::mvc::action_argument());" << std::endl;
  423. if (type_map.contains(type)) {
  424. ss << "\t\t\targument->argument_type_ = " << type_map[type] << ";" << std::endl;
  425. if (method_type == "POST") {
  426. if (!FromQuery.empty()) {
  427. ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::QUERY;" << std::endl;
  428. ss << fmt::format("\t\t\targument->parameter_name_ = \"{}\";", FromQuery[0].string_value.empty() ? name : FromQuery[0].string_value) << std::endl;
  429. }
  430. else if (!FromBody.empty()) {
  431. ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::BODY;" << std::endl;
  432. ss << fmt::format("\t\t\targument->parameter_name_ = \"{}\";", FromBody[0].string_value) << std::endl;
  433. }
  434. else if (!FromHeader.empty()) {
  435. ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::HEADER;" << std::endl;
  436. ss << fmt::format("\t\t\targument->parameter_name_ = \"{}\";", FromHeader[0].string_value.empty() ? name : FromHeader[0].string_value) << std::endl;
  437. }
  438. else {
  439. ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::BODY;" << std::endl;
  440. ss << fmt::format("\t\t\targument->parameter_name_ = \"{}\";", name) << std::endl;
  441. }
  442. }
  443. else {
  444. if (!FromQuery.empty()) {
  445. ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::QUERY;" << std::endl;
  446. ss << fmt::format("\t\t\targument->parameter_name_ = \"{}\";", FromQuery[0].string_value.empty() ? name : FromQuery[0].string_value) << std::endl;
  447. }
  448. else if (!FromUrl.empty()) {
  449. ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::URL;" << std::endl;
  450. ss << fmt::format("\t\t\targument->parameter_name_ = \"{}\";", FromUrl[0].string_value.empty() ? name : FromUrl[0].string_value) << std::endl;
  451. }
  452. else if (!FromHeader.empty()) {
  453. ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::HEADER;" << std::endl;
  454. ss << fmt::format("\t\t\targument->parameter_name_ = \"{}\";", FromHeader[0].string_value.empty() ? name : FromHeader[0].string_value) << std::endl;
  455. }
  456. else {
  457. ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::QUERY;" << std::endl;
  458. ss << fmt::format("\t\t\targument->parameter_name_ = \"{}\";", name) << std::endl;
  459. }
  460. }
  461. }
  462. else if (type == "robotics::v3::mvc::multipart_value" || type == "v3::mvc::multipart_value" || type == "mvc::multipart_value") {
  463. ss << "\t\t\targument->argument_type_ = " << type_map["Multipart"] << ";" << std::endl;
  464. ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::BODY;" << std::endl;
  465. ss << "\t\t\targument->parameter_name_ = \"\";" << std::endl;
  466. }
  467. else if (type.size() > 12 && type.substr(0, 11) == "std::vector") {
  468. ss << "\t\t\targument->argument_type_ = " << type_map["VecJson"] << ";" << std::endl;
  469. ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::BODY;" << std::endl;
  470. ss << "\t\t\targument->parameter_name_ = \"\";" << std::endl;
  471. }
  472. else {
  473. ss << "\t\t\targument->argument_type_ = " << type_map["Json"] << ";" << std::endl;
  474. ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::BODY;" << std::endl;
  475. ss << "\t\t\targument->parameter_name_ = \"\";" << std::endl;
  476. }
  477. ss << "\t\t\taction->arguments.push_back(argument);" << std::endl;
  478. ss << "\t\t}" << std::endl;
  479. return ss.str();
  480. }
  481. std::string generate_soap_code() {
  482. static std::map<std::string, std::string> type_map = {
  483. {"int","robotics::v3::soap_argument_type::Int"},
  484. {"std::int64_t","robotics::v3::soap_argument_type::Int64"},
  485. {"float","robotics::v3::soap_argument_type::Float"},
  486. {"double","robotics::v3::soap_argument_type::Double"},
  487. {"long","robotics::v3::soap_argument_type::Long"},
  488. {"bool","robotics::v3::soap_argument_type::Bool_"},
  489. {"std::string","robotics::v3::soap_argument_type::String"},
  490. {"robotics::v3::datetime","robotics::v3::soap_argument_type::DateTime"},
  491. {"v3::datetime","robotics::v3::soap_argument_type::DateTime"},
  492. {"datetime","robotics::v3::soap_argument_type::DateTime"}
  493. };
  494. std::stringstream ss;
  495. ss << "\t\t{" << std::endl;
  496. ss << "\t\t\tstd::shared_ptr<robotics::v3::soap_action_argument> argument(new robotics::v3::soap_action_argument());" << std::endl;
  497. if (type_map.contains(type)) {
  498. ss << fmt::format("\t\t\targument->argument_type_ = {};", type_map[type]) << std::endl;
  499. }
  500. ss << fmt::format("\t\t\targument->parameter_name_ = \"{}\";", name) << std::endl;
  501. ss << "\t\t\taction->arguments.push_back(argument);" << std::endl;
  502. ss << "\t\t}" << std::endl;
  503. return ss.str();
  504. }
  505. private:
  506. /**
  507. * @brief 反序列化
  508. * @param code
  509. */
  510. void deserialize(std::string code) {
  511. std::smatch smatch;
  512. if (std::regex_search(code, smatch, utils::regex::parameter())) {
  513. if (smatch.size() == 6) {
  514. type = smatch[4];
  515. name = smatch[5];
  516. for (auto& it : get_attributes(smatch[1])) {
  517. attributes.push_back(class_attribute_info(it));
  518. }
  519. }
  520. }
  521. }
  522. /**
  523. * @brief 获取特性列表
  524. * @param code
  525. * @return
  526. */
  527. std::vector<std::string> get_attributes(std::string code) {
  528. std::vector<std::string> result;
  529. std::smatch smatch;
  530. while (std::regex_search(code, smatch, utils::regex::attribute())) {
  531. if (smatch.size() == 3) {
  532. result.push_back(smatch[0]);
  533. }
  534. code = smatch.suffix();
  535. }
  536. return result;
  537. }
  538. };
  539. struct class_method_info {
  540. class_method_info() {}
  541. class_method_info(std::string code) :
  542. content(code) {
  543. deserialize(code);
  544. }
  545. std::string content;
  546. std::string result;
  547. std::string name;
  548. std::string signature;
  549. std::vector<class_parameter_info> parameters;
  550. std::vector<class_attribute_info> attributes;
  551. std::string generate_code() {
  552. if (parameters.empty()) {
  553. return fmt::format("method(\"{}\",&{{}}::{})",
  554. name,
  555. name);
  556. }
  557. else {
  558. std::vector<std::string> param_names;
  559. std::vector<std::string> param_types;
  560. for (auto& it : parameters) {
  561. param_names.push_back(fmt::format("\"{}\"", it.name));
  562. param_types.push_back(fmt::format("{}{{{{}}}}", it.type));
  563. }
  564. return fmt::format("method(\"{}\",&{{}}::{})(rttr::default_arguments({}),rttr::parameter_names({}))",
  565. name,
  566. name,
  567. utils::string::join(param_types, ","),
  568. utils::string::join(param_names, ","));
  569. }
  570. }
  571. std::string generate_cntlr_code() {
  572. std::stringstream ss;
  573. auto ActionType = utils::attribute::find(attributes, "ActionType");
  574. auto Method = utils::attribute::find(attributes, "Method");
  575. auto Authen = utils::attribute::find(attributes, "Authen");
  576. auto Route = utils::attribute::find(attributes, "Route");
  577. auto ContentType = utils::attribute::find(attributes, "ContentType");
  578. auto FileMapping = utils::attribute::find(attributes, "FileMapping");
  579. ss << "\t{" << std::endl;
  580. ss << "\t\tstd::shared_ptr<robotics::v3::mvc::controller_action> action(new robotics::v3::mvc::controller_action());" << std::endl;
  581. for (auto& it : parameters) {
  582. if (!Method.empty()) {
  583. ss << it.generate_cntlr_code(Method[0].string_value == "POST" ? "POST" : "GET");
  584. }
  585. else {
  586. ss << it.generate_cntlr_code("GET");
  587. }
  588. }
  589. ss << fmt::format("\t\taction->action_name = \"{}\";", name) << std::endl;
  590. ss << "\t\taction->parent = controller;" << std::endl;
  591. if (!Authen.empty()) {
  592. ss << fmt::format("\t\taction->authen = {};", Authen[0].bool_value ? "true" : "false") << std::endl;
  593. ss << fmt::format("\t\taction->authen_jump = \"{}\";", Authen[0].string_value) << std::endl;
  594. }
  595. else {
  596. ss << "\t\taction->authen = true;" << std::endl;
  597. ss << "\t\taction->authen_jump = \"\";" << std::endl;
  598. }
  599. if (!ContentType.empty()) {
  600. ss << fmt::format("\t\taction->content_type = \"{}\";", ContentType[0].string_value.empty() ? "application/x-www-form-urlencoded" : ContentType[0].string_value) << std::endl;
  601. }
  602. else {
  603. ss << "\t\taction->content_type = \"application/x-www-form-urlencoded\";" << std::endl;
  604. }
  605. if (!ActionType.empty()) {
  606. ss << fmt::format("\t\taction->action_type = \"{}\";", ActionType[0].string_value) << std::endl;
  607. }
  608. else {
  609. ss << "\t\taction->action_type = \"\";" << std::endl;
  610. }
  611. if (!FileMapping.empty()) {
  612. ss << fmt::format("\t\taction->file_mapping = \"{}\";", FileMapping[0].string_value) << std::endl;
  613. }
  614. else {
  615. ss << "\t\taction->file_mapping = \"\";" << std::endl;
  616. }
  617. if (!Method.empty()) {
  618. if (Method[0].string_value == "POST") {
  619. ss << "\t\taction->method = robotics::v3::mvc::http_method::POST;" << std::endl;
  620. }
  621. else {
  622. ss << "\t\taction->method = robotics::v3::mvc::http_method::GET;" << std::endl;
  623. }
  624. }
  625. else {
  626. ss << "\t\taction->method = robotics::v3::mvc::http_method::GET;" << std::endl;
  627. }
  628. if (!Route.empty()) {
  629. ss << fmt::format("\t\tcontroller->actions[\"{}\"] = action;", Route[0].string_value.empty() ? name : Route[0].string_value) << std::endl;
  630. }
  631. else {
  632. ss << fmt::format("\t\tcontroller->actions[\"{}\"] = action;", name) << std::endl;
  633. }
  634. ss << "\t}" << std::endl;
  635. return ss.str();
  636. }
  637. std::string generate_soap_code() {
  638. auto Method = utils::attribute::find(attributes, "Method");
  639. std::stringstream ss;
  640. ss << "\t{" << std::endl;
  641. ss << "\t\tstd::shared_ptr<robotics::v3::soap_controller_action> action(new robotics::v3::soap_controller_action());" << std::endl;
  642. for (auto& it : parameters) {
  643. ss << it.generate_soap_code();
  644. }
  645. ss << fmt::format("\t\taction->action_name = \"{}\";", name) << std::endl;
  646. if (!Method.empty()) {
  647. ss << fmt::format("\t\tcontroller->actions[\"{}\"] = action;", Method[0].string_value.empty() ? name : Method[0].string_value) << std::endl;
  648. }
  649. else {
  650. ss << fmt::format("\t\tcontroller->actions[\"{}\"] = action;", name) << std::endl;
  651. }
  652. ss << "\t}" << std::endl;
  653. return ss.str();
  654. }
  655. private:
  656. /**
  657. * @brief 反序列化
  658. * @param code
  659. */
  660. void deserialize(std::string code) {
  661. std::smatch smatch;
  662. if (std::regex_search(code, smatch, utils::regex::method())) {
  663. if (smatch.size() == 5) {
  664. std::vector<std::string> params;
  665. result = smatch[2];
  666. name = smatch[3];
  667. for (auto& it : get_parameters(smatch[4])) {
  668. parameters.push_back(class_parameter_info(it));
  669. params.push_back(parameters[parameters.size() - 1].type);
  670. }
  671. for (auto& it : get_attributes(smatch[1])) {
  672. attributes.push_back(class_attribute_info(it));
  673. }
  674. signature = result + "(" + utils::string::join(params) + ")";
  675. }
  676. }
  677. }
  678. /**
  679. * @brief 获取特性列表
  680. * @param code
  681. * @return
  682. */
  683. std::vector<std::string> get_attributes(std::string code) {
  684. std::vector<std::string> result;
  685. std::smatch smatch;
  686. while (std::regex_search(code, smatch, utils::regex::attribute())) {
  687. if (smatch.size() == 3) {
  688. result.push_back(smatch[0]);
  689. }
  690. code = smatch.suffix();
  691. }
  692. return result;
  693. }
  694. /**
  695. * @brief 获取参数列表
  696. * @param code
  697. * @return
  698. */
  699. std::vector<std::string> get_parameters(std::string code) {
  700. std::vector<std::string> result;
  701. std::smatch smatch;
  702. while (std::regex_search(code, smatch, utils::regex::parameter())) {
  703. if (smatch.size() == 6) {
  704. result.push_back(smatch[0]);
  705. }
  706. code = smatch.suffix();
  707. }
  708. return result;
  709. }
  710. };
  711. struct class_view_info {
  712. class_view_info() {}
  713. class_view_info(std::string code, int type) :
  714. content(code),
  715. class_type(type) {
  716. deserialize(code);
  717. }
  718. int class_type = 0;
  719. std::string content;
  720. std::string type;
  721. std::string name;
  722. bool is_tmpl = false;
  723. std::vector<std::string> tmpl_params;
  724. std::vector<class_attribute_info> attributes;
  725. std::vector<class_property_info> propertys;
  726. std::vector<class_method_info> cntlr_methods;
  727. std::vector<class_method_info> soap_methods;
  728. std::pair<std::string, std::string> generate_code() {
  729. std::stringstream ss;
  730. std::string funcname = fmt::format("func_{}()", utils::string::generate_hex(16));
  731. ss << "static void " << funcname << " {" << std::endl;
  732. if (class_type == 0) {
  733. auto SqlTable = utils::attribute::find(attributes, "SqlTable");
  734. auto NoReflect = utils::attribute::find(attributes, "NoReflect");
  735. auto TemplateType = utils::attribute::find(attributes, "TemplateType");
  736. if (NoReflect.empty() || (!NoReflect.empty() && !NoReflect[0].bool_value)) {
  737. if (!is_tmpl) {
  738. std::vector<std::string> item;
  739. item.push_back(fmt::format("\trttr::registration::class_<{} {}>(\"{}\").constructor<>()(rttr::detail::as_object{{}})", type, name, SqlTable.empty() ? name : SqlTable[0].string_value));
  740. for (auto it : propertys) {
  741. item.push_back(fmt::vformat(it.generate_code(), fmt::make_format_args(name)));
  742. }
  743. if (item.size() > 1) {
  744. ss << utils::string::join(item, ".\n\t\t") << ";" << std::endl;
  745. }
  746. }
  747. else {
  748. std::vector<std::string> class_propertys;
  749. for (auto it : propertys) {
  750. class_propertys.push_back(it.generate_code());
  751. }
  752. for (auto it : TemplateType) {
  753. std::vector<std::string> item;
  754. std::string tablename = name + "<" + utils::string::join(it.vector_string_value, ",") + ">";
  755. item.push_back(fmt::format("\trttr::registration::class_<{} {}>(\"{}\").constructor<>()(rttr::detail::as_object{{}})", type, tablename, tablename));
  756. for (auto it1 : class_propertys) {
  757. item.push_back(fmt::vformat(it1, fmt::make_format_args(tablename)));
  758. }
  759. if (item.size() > 1) {
  760. ss << utils::string::join(item, ".\n\t\t") << ";" << std::endl;
  761. }
  762. }
  763. }
  764. }
  765. }
  766. else if (class_type == 1) {
  767. auto NoReflect = utils::attribute::find(attributes, "NoReflect");
  768. if (NoReflect.empty() || (!NoReflect.empty() && !NoReflect[0].bool_value)) {
  769. std::vector<std::string> item;
  770. item.push_back(fmt::format("\trttr::registration::class_<{} {}>(\"{}\").constructor<>()()", type, name, name));
  771. for (auto it : cntlr_methods) {
  772. item.push_back(fmt::vformat(it.generate_code(), fmt::make_format_args(name)));
  773. }
  774. if (item.size() > 1) {
  775. ss << utils::string::join(item, ".\n\t\t") << ";" << std::endl;
  776. }
  777. }
  778. ss << "\tstd::shared_ptr<robotics::v3::mvc::controller> controller(new robotics::v3::mvc::controller());" << std::endl;
  779. for (auto& it : cntlr_methods) {
  780. ss << it.generate_cntlr_code();
  781. }
  782. ss << fmt::format("\tcontroller->controller_name = \"{}\";", name) << std::endl;
  783. ss << "\trobotics::v3::mvc::ico_controller::attach(controller);" << std::endl;
  784. }
  785. else if (class_type == 2) {
  786. auto NoReflect = utils::attribute::find(attributes, "NoReflect");
  787. auto Route = utils::attribute::find(attributes, "Route");
  788. auto Version = utils::attribute::find(attributes, "Version");
  789. auto Namespace = utils::attribute::find(attributes, "Namespace");
  790. auto Wsdl = utils::attribute::find(attributes, "Wsdl");
  791. if (NoReflect.empty() || (!NoReflect.empty() && !NoReflect[0].bool_value)) {
  792. std::vector<std::string> item;
  793. item.push_back(fmt::format("\trttr::registration::class_<{} {}>(\"{}\").constructor<>()()", type, name, name));
  794. for (auto it : soap_methods) {
  795. item.push_back(fmt::vformat(it.generate_code(), fmt::make_format_args(name)));
  796. }
  797. if (item.size() > 1) {
  798. ss << utils::string::join(item, ".\n\t\t") << ";" << std::endl;
  799. }
  800. ss << "\tstd::shared_ptr<robotics::v3::soap_controller> controller(new robotics::v3::soap_controller());" << std::endl;
  801. for (auto& it : soap_methods) {
  802. ss << it.generate_soap_code();
  803. }
  804. ss << fmt::format("\tcontroller->controller_name = \"{}\";", name) << std::endl;
  805. if (!Wsdl.empty()) {
  806. ss << fmt::format("\tcontroller->wsdl = \"{}\";", Wsdl[0].string_value) << std::endl;
  807. }
  808. else {
  809. ss << "\tstatic_assert(false, \"wsdl path error\");" << std::endl;
  810. }
  811. if (!Route.empty()) {
  812. ss << fmt::format("\tcontroller->route = \"{}\";", Route[0].string_value) << std::endl;
  813. }
  814. else {
  815. ss << "\tstatic_assert(false, \"route path error\");" << std::endl;
  816. }
  817. if (!Namespace.empty()) {
  818. ss << fmt::format("\tcontroller->namespace_name = \"{}\";", Namespace[0].string_value) << std::endl;
  819. }
  820. else {
  821. ss << "\tstatic_assert(false, \"namespace path error\");" << std::endl;
  822. }
  823. if (!Version.empty()) {
  824. ss << fmt::format("\tcontroller->version = {};", Version[0].string_value == "1.1" ? "robotics::v3::soap_version::VER1_1" : "robotics::v3::soap_version::VER1_2") << std::endl;
  825. }
  826. else {
  827. ss << "\tcontroller->version = robotics::v3::soap_version::VER1_1;" << std::endl;
  828. }
  829. ss << "\trobotics::v3::soap_ioc_controller::attach(controller);" << std::endl;
  830. }
  831. }
  832. ss << "}" << std::endl;
  833. return std::pair(funcname, ss.str());
  834. }
  835. private:
  836. /**
  837. * @brief
  838. * @param code
  839. */
  840. void deserialize(std::string code) {
  841. std::smatch smatch;
  842. if (std::regex_search(code, smatch, utils::regex::class_())) {
  843. if (smatch.size() == 5) {
  844. std::string tmp_code = smatch.suffix();
  845. std::size_t index = tmp_code.find('{');
  846. if (index != std::string::npos && utils::string::ergodic(tmp_code, index)) {
  847. tmpl_params = get_tmpl_params(smatch[1]);
  848. type = smatch[2];
  849. name = smatch[4];
  850. is_tmpl = !smatch[1].str().empty();
  851. for (auto& it : get_attributes(smatch[3])) {
  852. attributes.push_back(class_attribute_info(it));
  853. }
  854. if (class_type == 0) {
  855. for (auto& it : get_propertys(tmp_code.substr(0, index + 1))) {
  856. propertys.push_back(class_property_info(it));
  857. }
  858. }
  859. else if (class_type == 1) {
  860. for (auto& it : get_methods(tmp_code.substr(0, index + 1))) {
  861. cntlr_methods.push_back(class_method_info(it));
  862. }
  863. }
  864. else if (class_type == 2) {
  865. for (auto& it : get_methods(tmp_code.substr(0, index + 1))) {
  866. soap_methods.push_back(class_method_info(it));
  867. }
  868. }
  869. code = smatch.suffix().str().substr(index + 1);
  870. }
  871. else {
  872. code = smatch.suffix();
  873. }
  874. }
  875. else {
  876. code = smatch.suffix();
  877. }
  878. }
  879. }
  880. /**
  881. * @brief 获取特性列表
  882. * @param code
  883. * @return
  884. */
  885. std::vector<std::string> get_attributes(std::string code) {
  886. std::vector<std::string> result;
  887. std::smatch smatch;
  888. while (std::regex_search(code, smatch, utils::regex::attribute())) {
  889. if (smatch.size() == 3) {
  890. result.push_back(smatch[0]);
  891. }
  892. code = smatch.suffix();
  893. }
  894. return result;
  895. }
  896. /**
  897. * @brief 获取模板参数名称
  898. * @param code
  899. * @return
  900. */
  901. std::vector<std::string> get_tmpl_params(std::string code) {
  902. std::vector<std::string> result;
  903. std::smatch smatch;
  904. while (std::regex_search(code, smatch, utils::regex::template_())) {
  905. if (smatch.size() == 2) {
  906. auto params = utils::string::split(smatch[1]);
  907. for (auto it : params) {
  908. it = utils::string::replace(it, "typename", "");
  909. result.push_back(utils::string::trim(it));
  910. }
  911. }
  912. code = smatch.suffix();
  913. }
  914. return result;
  915. }
  916. /**
  917. * @brief 获取属性列表
  918. * @param code
  919. * @return
  920. */
  921. std::vector<std::string> get_propertys(std::string code) {
  922. std::vector<std::string> result;
  923. std::smatch smatch;
  924. while (std::regex_search(code, smatch, utils::regex::property())) {
  925. if (smatch.size() == 4) {
  926. result.push_back(smatch[0]);
  927. }
  928. code = smatch.suffix();
  929. }
  930. return result;
  931. }
  932. /**
  933. * @brief
  934. * @param code
  935. * @return
  936. */
  937. std::vector<std::string> get_methods(std::string code) {
  938. std::vector<std::string> result;
  939. std::smatch smatch;
  940. while (std::regex_search(code, smatch, utils::regex::method())) {
  941. if (smatch.size() == 5) {
  942. result.push_back(smatch[0]);
  943. }
  944. code = smatch.suffix();
  945. }
  946. return result;
  947. }
  948. };
  949. struct class_code_info {
  950. class_code_info() {}
  951. class_code_info(std::string code, int _type, std::string path, std::string relative_path) :
  952. content(code),
  953. type(_type),
  954. root_directory(path),
  955. relative_directory(relative_path) {
  956. deserialize(code);
  957. }
  958. //0实体类,1web控制器,2saop控制器
  959. int type = 0;
  960. std::string root_directory;
  961. std::string content;
  962. std::string relative_directory;
  963. std::vector<class_view_info> views;
  964. std::pair<std::vector<std::string>, std::string> generate_code() {
  965. std::vector<std::string> funclist;
  966. std::stringstream ss;
  967. for (auto& it : views) {
  968. auto view_code = it.generate_code();
  969. funclist.push_back(view_code.first);
  970. ss << view_code.second;
  971. }
  972. return std::pair(funclist, ss.str());
  973. }
  974. private:
  975. /**
  976. * @brief
  977. * @param code
  978. */
  979. void deserialize(std::string code) {
  980. delete_excess(code);
  981. std::smatch smatch;
  982. while (std::regex_search(code, smatch, utils::regex::class_())) {
  983. if (smatch.size() == 5) {
  984. std::string src = smatch[0];
  985. std::string tmp_code = smatch.suffix();
  986. std::size_t index = tmp_code.find('{');
  987. if (index != std::string::npos && utils::string::ergodic(tmp_code, index)) {
  988. src += tmp_code.substr(0, index + 1);
  989. views.push_back(class_view_info(src, type));
  990. code = smatch.suffix().str().substr(index + 1);
  991. }
  992. else {
  993. code = smatch.suffix();
  994. }
  995. }
  996. else {
  997. code = smatch.suffix();
  998. }
  999. }
  1000. }
  1001. /**
  1002. * @brief 删除注释
  1003. * @param code
  1004. */
  1005. void delete_excess(std::string& code) {
  1006. static std::vector<std::pair<std::string, std::string>> notes = {
  1007. {"/*","*/"},
  1008. {"//","\n"},
  1009. {"#include","\n"},
  1010. {"#pragma", "\n"},
  1011. {"#ifndef", "\n"},
  1012. {"#define", "\n"},
  1013. {"#if", "\n"},
  1014. {"#endif", "\n"}
  1015. };
  1016. for (auto& note : notes) {
  1017. std::size_t begin = 0;
  1018. std::size_t end = 0;
  1019. while ((begin = code.find(note.first, begin)) != std::string::npos && (end = code.find(note.second, begin)) != std::string::npos) {
  1020. if (begin > 0 && code[begin - 1] == ':') {
  1021. begin += note.second.size();
  1022. continue;
  1023. }
  1024. code.erase(begin, end - begin + note.second.size());
  1025. code.insert(code.begin() + begin, ' ');
  1026. begin++;
  1027. }
  1028. }
  1029. }
  1030. };
  1031. class code_analysis {
  1032. public:
  1033. static std::string generate_code(std::string const& path) {
  1034. std::stringstream ss;
  1035. std::vector<std::string> funclist;
  1036. //解析代码
  1037. auto values = code_analysis(path).get_class_code();
  1038. //生成时间
  1039. ss << "//生成时间:" << utils::string::current_time() << std::endl;
  1040. ss << "#pragma once" << std::endl;
  1041. ss << "#include <rttr/registration>" << std::endl;
  1042. ss << "#include <robotics/logger.hpp>" << std::endl;
  1043. //头文件
  1044. for (auto& it : values) {
  1045. ss << "#include \"" << it.relative_directory << "\"" << std::endl;
  1046. }
  1047. ss << std::endl;
  1048. for (auto& it : values) {
  1049. auto view_code = it.generate_code();
  1050. funclist.insert(funclist.end(), view_code.first.begin(), view_code.first.end());
  1051. ss << view_code.second;
  1052. }
  1053. ss << "RTTR_REGISTRATION {" << std::endl;
  1054. ss << "\t" << utils::string::join(funclist, ";\n\t") << ";" << std::endl;
  1055. ss << "}" << std::endl;
  1056. return ss.str();
  1057. }
  1058. static std::vector<class_code_info> get_class_code(std::string const& path) {
  1059. return code_analysis(path).get_class_code();
  1060. }
  1061. private:
  1062. code_analysis(std::string const& path) :
  1063. path_(path) {
  1064. path_ = utils::string::replace(path_, "\\", "/");
  1065. if (path_[path_.size() - 1] != '/') {
  1066. path_ += '/';
  1067. }
  1068. }
  1069. std::vector<class_code_info> get_class_code() {
  1070. std::vector<class_code_info> result;
  1071. auto values = get_models();
  1072. result.insert(result.end(), values.begin(), values.end());
  1073. values = get_controllers();
  1074. result.insert(result.end(), values.begin(), values.end());
  1075. values = get_webservices();
  1076. result.insert(result.end(), values.begin(), values.end());
  1077. return result;
  1078. }
  1079. std::vector<class_code_info> get_models() {
  1080. std::vector<class_code_info> result;
  1081. for (auto& it : get_files(path_ + "models", { ".h" })) {
  1082. result.push_back(class_code_info(get_code(path_ + it), 0, path_, it));
  1083. }
  1084. return result;
  1085. }
  1086. std::vector<class_code_info> get_controllers() {
  1087. std::vector<class_code_info> result;
  1088. for (auto& it : get_files(path_ + "controllers", { ".hpp" })) {
  1089. result.push_back(class_code_info(get_code(path_ + it), 1, path_, it));
  1090. result[result.size() - 1].root_directory = path_;
  1091. result[result.size() - 1].relative_directory = it;
  1092. result[result.size() - 1].type = 1;
  1093. }
  1094. return result;
  1095. }
  1096. std::vector<class_code_info> get_webservices() {
  1097. std::vector<class_code_info> result;
  1098. for (auto& it : get_files(path_ + "webservices", { ".hpp" })) {
  1099. result.push_back(class_code_info(get_code(path_ + it), 2, path_, it));
  1100. result[result.size() - 1].root_directory = path_;
  1101. result[result.size() - 1].relative_directory = it;
  1102. result[result.size() - 1].type = 2;
  1103. }
  1104. return result;
  1105. }
  1106. std::string get_code(std::string const& path) {
  1107. std::ifstream file(path, std::ios::out);
  1108. if (file.is_open()) {
  1109. return std::string((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
  1110. }
  1111. return "";
  1112. }
  1113. std::vector<std::string> get_files(std::string const& path, std::vector<std::string> const& extension) {
  1114. std::vector<std::string> result;
  1115. if (!std::filesystem::is_directory(path)) {
  1116. return result;
  1117. }
  1118. for (auto& itr : std::filesystem::directory_iterator(path)) {
  1119. if (std::filesystem::is_directory(itr.status())) {
  1120. auto values = get_files(itr.path().string(), extension);
  1121. result.insert(result.end(), values.begin(), values.end());
  1122. }
  1123. else {
  1124. if (std::find(extension.begin(), extension.end(), itr.path().extension()) != extension.end()) {
  1125. std::string tmp = itr.path().string();
  1126. tmp = utils::string::replace(tmp, "\\", "/");
  1127. tmp = utils::string::replace(tmp, path_, "");
  1128. result.push_back(tmp);
  1129. }
  1130. }
  1131. }
  1132. return result;
  1133. }
  1134. private:
  1135. std::string path_;
  1136. };
  1137. }