1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147 |
- #pragma once
- #include <iostream>
- #include <filesystem>
- #include <regex>
- #include <map>
- #include <any>
- #include <variant>
- #include <fstream>
- #include <chrono>
- #include <random>
- #include <fmt/format.h>
- namespace analysis {
- struct class_attribute_info;
- /**
- * @brief 工具
- */
- class utils {
- public:
- /**
- * @brief 字符串
- */
- class string {
- public:
- /**
- * @brief 替换
- * @param value
- * @param old_str
- * @param new_str
- * @return
- */
- static std::string replace(std::string const& value, std::string const& old_str, std::string const& new_str) {
- std::string result = value;
- for (std::string::size_type pos(0); pos != std::string::npos; pos += new_str.length()) {
- pos = result.find(old_str, pos);
- if (pos != std::string::npos)
- result.replace(pos, old_str.length(), new_str);
- else
- break;
- }
- return result;
- }
- /**
- * @brief 分割字符串
- * @param value
- * @return
- */
- static std::vector<std::string> split(std::string const& value) {
- std::string c = ",";
- std::vector<std::string> result;
- if (value.empty()) {
- return result;
- }
- std::string strs = value + c;
- size_t pos = strs.find(c);
- while (pos != strs.npos) {
- std::string temp = strs.substr(0, pos);
- result.push_back(temp);
- strs = strs.substr(pos + c.size(), strs.size());
- pos = strs.find(c);
- }
- return result;
- }
- /**
- * @brief
- * @param values
- * @return
- */
- static std::string join(std::vector<std::string> values, std::string c = ",") {
- std::string result;
- while (!values.empty()) {
- if (result.empty()) {
- result = values[0];
- values.erase(values.begin());
- }
- else {
- result += c + values[0];
- values.erase(values.begin());
- }
- }
- return result;
- }
- /**
- * @brief 删除首尾空格
- * @param value
- * @return
- */
- static std::string trim(std::string const& value) {
- std::string result = value;
- while (!result.empty()) {
- if (result[0] == ' ' || result[0] == '\t' || result[0] == '\r' || result[0] == '\n')
- result.erase(result.begin());
- else
- break;
- }
- while (!result.empty()) {
- if (result[result.size() - 1] == ' ' || result[result.size() - 1] == '\t' || result[result.size() - 1] == '\r' || result[result.size() - 1] == '\n')
- result.pop_back();
- else
- break;
- }
- return result;
- }
- /**
- * @brief 大括号
- * @param code
- * @param index
- * @return
- */
- static bool ergodic(std::string& code, std::size_t& index) {
- index++;
- for (; index < code.size(); ++index) {
- if (code[index] == '}' || code[index] == ')') {
- return true;
- }
- else if (code[index] == '{') {
- ergodic(code, index);
- }
- else if (code[index] == '(') {
- ergodic(code, index);
- }
- else if (code[index] == '"') {
- quotation_mark(code, index);
- }
- }
- return false;
- }
- /**
- * @brief 引号
- * @param code
- * @param index
- * @return
- */
- static bool quotation_mark(std::string& code, std::size_t& index) {
- index++;
- for (; index < code.size(); ++index) {
- if (code[index] == '"') {
- return true;
- }
- }
- return false;
- }
- /**
- * @brief
- * @return
- */
- static unsigned int random_char() {
- std::random_device rd;
- std::mt19937 gen(rd());
- std::uniform_int_distribution<> dis(0, 255);
- return dis(gen);
- }
- /**
- * @brief
- * @param len
- * @return
- */
- static std::string generate_hex(const unsigned int len) {
- std::stringstream ss;
- for (unsigned int i = 0; i < len; i++) {
- const auto rc = random_char();
- std::stringstream hexstream;
- hexstream << std::hex << rc;
- auto hex = hexstream.str();
- ss << (hex.length() < 2 ? '0' + hex : hex);
- }
- return ss.str();
- }
- /**
- * @brief 当前时间
- * @return
- */
- static std::string current_time() {
- std::time_t timestamp = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
- std::tm now_time;
- #ifdef WINDOWS_BUILD
- localtime_s(&now_time, ×tamp);
- #elif LINUX_BUILD
- localtime_r(×tamp, &now_time);
- #endif
- std::stringstream ss;
- ss << std::put_time(&now_time, "%Y-%m-%d %H:%M:%S");
- return ss.str();
- }
- };
- /**
- * @brief 正则表达式
- */
- class regex {
- public:
- /**
- * @brief 特性
- * @return
- */
- static std::regex& attribute() {
- 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}\\)\\]\\]");
- return value;
- }
- /**
- * @brief 属性
- * @return
- */
- static std::regex& property() {
- 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})[^;]*;");
- return value;
- }
- /**
- * @brief 方法
- * @return
- */
- static std::regex& method() {
- 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})\\)");
- return value;
- }
- /**
- * @brief 类
- * @return
- */
- static std::regex& class_() {
- 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})");
- return value;
- }
- /**
- * @brief 模板
- * @return
- */
- static std::regex& template_() {
- static std::regex value("template[ \r\n\t]{0,30}<([\\s\\S]{1,100})>");
- return value;
- }
- /**
- * @brief 参数
- * @return
- */
- static std::regex& parameter() {
- 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})");
- return value;
- }
- };
- /**
- * @brief 特性
- */
- class attribute {
- public:
- //查找
- static std::vector<class_attribute_info> find(std::vector<class_attribute_info> const& src, std::string const& attribute);
- };
- };
- struct class_attribute_info {
- class_attribute_info() {}
- class_attribute_info(std::string code) :
- content(code) {
- deserialize(code);
- }
- std::string content;
- std::string attribute;
- bool bool_value = false;
- std::string string_value;
- std::vector<std::string> vector_string_value;
- std::vector<bool> vector_bool_value;
- private:
- /**
- * @brief
- * @param code
- */
- void deserialize(std::string code) {
- std::smatch smatch;
- if (std::regex_search(code, smatch, utils::regex::attribute())) {
- if (smatch.size() == 3) {
- std::vector<std::any> item;
- attribute = smatch[1];
- get_value(smatch[2]);
- }
- }
- }
- /**
- * @brief 获取值
- * @param code
- */
- void get_value(std::string code) {
- if (code.empty())
- return;
- auto params = utils::string::split(code);
- for (auto it : params) {
- it = utils::string::trim(it);
- if (attribute == "TemplateType") {
- if (it == "false" || it == "true") {
- vector_bool_value.push_back(it == "true");
- }
- else if (it.find('"') != std::string::npos) {
- vector_string_value.push_back(it.substr(1, it.size() - 2));
- }
- }
- else {
- if (it == "false" || it == "true") {
- bool_value = it == "true";
- }
- else if (it.find('"') != std::string::npos) {
- string_value = it.substr(1, it.size() - 2);
- }
- }
- }
- }
- };
- std::vector<class_attribute_info> utils::attribute::find(std::vector<class_attribute_info> const& src, std::string const& attribute) {
- std::vector<class_attribute_info> result;
- for (auto it : src) {
- if (it.attribute == attribute) {
- result.push_back(it);
- }
- }
- return result;
- }
- struct class_property_info {
- class_property_info() {}
- class_property_info(std::string code) :
- content(code) {
- deserialize(code);
- }
- std::string content;
- std::string type;
- std::string name;
- std::vector<class_attribute_info> attributes;
- std::string generate_code() {
- auto Json = utils::attribute::find(attributes, "Json");
- auto Sql = utils::attribute::find(attributes, "Sql");
- auto Excel = utils::attribute::find(attributes, "Excel");
- auto NoJson = utils::attribute::find(attributes, "NoJson");
- auto NoSql = utils::attribute::find(attributes, "NoSql");
- auto NoExcel = utils::attribute::find(attributes, "NoExcel");
- auto SqlKey = utils::attribute::find(attributes, "SqlKey");
- auto NoArchive = utils::attribute::find(attributes, "NoArchive");
- 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}}::{})))",
- name,
- name,
- Json.empty() ? name : Json[0].string_value,
- Sql.empty() ? name : Sql[0].string_value,
- Excel.empty() ? name : Excel[0].string_value,
- NoJson.empty() ? "false" : (NoJson[0].bool_value ? "true" : "false"),
- NoSql.empty() ? "false" : (NoSql[0].bool_value ? "true" : "false"),
- NoExcel.empty() ? "false" : (NoExcel[0].bool_value ? "true" : "false"),
- SqlKey.empty() ? "false" : (SqlKey[0].bool_value ? "true" : "false"),
- NoArchive.empty() ? "false" : (NoArchive[0].bool_value ? "true" : "false"),
- name);
- }
- private:
- /**
- * @brief 反序列化
- * @param code
- */
- void deserialize(std::string code) {
- std::smatch smatch;
- if (std::regex_search(code, smatch, utils::regex::property())) {
- if (smatch.size() == 4) {
- type = smatch[2];
- name = smatch[3];
- for (auto& it : get_attributes(smatch[1])) {
- attributes.push_back(class_attribute_info(it));
- }
- }
- }
- }
- /**
- * @brief 获取特性列表
- * @param code
- * @return
- */
- std::vector<std::string> get_attributes(std::string code) {
- std::vector<std::string> result;
- std::smatch smatch;
- while (std::regex_search(code, smatch, utils::regex::attribute())) {
- if (smatch.size() == 3) {
- result.push_back(smatch[0]);
- }
- code = smatch.suffix();
- }
- return result;
- }
- };
- struct class_parameter_info {
- class_parameter_info() {}
- class_parameter_info(std::string code) :
- content(code) {
- deserialize(code);
- }
- std::string content;
- std::string type;
- std::string name;
- std::vector<class_attribute_info> attributes;
- std::string generate_cntlr_code(std::string const& method_type) {
- static std::map<std::string, std::string> type_map = {
- {"int", "robotics::v3::mvc::argument_type::Int"},
- {"std::int64_t", "robotics::v3::mvc::argument_type::Int64"},
- {"float", "robotics::v3::mvc::argument_type::Float"},
- {"double", "robotics::v3::mvc::argument_type::Double"},
- {"long", "robotics::v3::mvc::argument_type::Long"},
- {"bool", "robotics::v3::mvc::argument_type::Bool_"},
- {"std::string", "robotics::v3::mvc::argument_type::String"},
- {"robotics::v3::datetime", "robotics::v3::mvc::argument_type::DateTime"},
- {"v3::datetime", "robotics::v3::mvc::argument_type::DateTime"},
- {"datetime", "robotics::v3::mvc::argument_type::DateTime"},
- {"std::vector<std::uint8_t>", "robotics::v3::mvc::argument_type::Binary"},
- {"std::vector<int>", "robotics::v3::mvc::argument_type::VecInt"},
- {"std::vector<std::int64_t>", "robotics::v3::mvc::argument_type::VecInt64"},
- {"std::vector<float>", "robotics::v3::mvc::argument_type::VecFloat"},
- {"std::vector<double>", "robotics::v3::mvc::argument_type::VecDouble"},
- {"std::vector<long>", "robotics::v3::mvc::argument_type::VecLong"},
- {"std::vector<bool>", "robotics::v3::mvc::argument_type::VecBool"},
- {"std::vector<std::string>", "robotics::v3::mvc::argument_type::VecString"},
- {"std::vector<robotics::v3::datetime>", "robotics::v3::mvc::argument_type::VecDateTime"},
- {"std::vector<v3::datetime>", "robotics::v3::mvc::argument_type::VecDateTime"},
- {"std::vector<datetime>", "robotics::v3::mvc::argument_type::VecDateTime"},
- {"VecJson", "robotics::v3::mvc::argument_type::VecJson"},
- {"Json", "robotics::v3::mvc::argument_type::Json"},
- {"Multipart", "robotics::v3::mvc::argument_type::Multipart"}
- };
- auto FromQuery = utils::attribute::find(attributes, "FromQuery");
- auto FromBody = utils::attribute::find(attributes, "FromBody");
- auto FromHeader = utils::attribute::find(attributes, "FromHeader");
- auto FromUrl = utils::attribute::find(attributes, "FromUrl");
- std::stringstream ss;
- ss << "\t\t{" << std::endl;
- ss << "\t\t\tstd::shared_ptr<robotics::v3::mvc::action_argument> argument(new robotics::v3::mvc::action_argument());" << std::endl;
- if (type_map.contains(type)) {
- ss << "\t\t\targument->argument_type_ = " << type_map[type] << ";" << std::endl;
- if (method_type == "POST") {
- if (!FromQuery.empty()) {
- ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::QUERY;" << std::endl;
- ss << fmt::format("\t\t\targument->parameter_name_ = \"{}\";", FromQuery[0].string_value.empty() ? name : FromQuery[0].string_value) << std::endl;
- }
- else if (!FromBody.empty()) {
- ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::BODY;" << std::endl;
- ss << fmt::format("\t\t\targument->parameter_name_ = \"{}\";", FromBody[0].string_value) << std::endl;
- }
- else if (!FromHeader.empty()) {
- ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::HEADER;" << std::endl;
- ss << fmt::format("\t\t\targument->parameter_name_ = \"{}\";", FromHeader[0].string_value.empty() ? name : FromHeader[0].string_value) << std::endl;
- }
- else {
- ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::BODY;" << std::endl;
- ss << fmt::format("\t\t\targument->parameter_name_ = \"{}\";", name) << std::endl;
- }
- }
- else {
- if (!FromQuery.empty()) {
- ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::QUERY;" << std::endl;
- ss << fmt::format("\t\t\targument->parameter_name_ = \"{}\";", FromQuery[0].string_value.empty() ? name : FromQuery[0].string_value) << std::endl;
- }
- else if (!FromUrl.empty()) {
- ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::URL;" << std::endl;
- ss << fmt::format("\t\t\targument->parameter_name_ = \"{}\";", FromUrl[0].string_value.empty() ? name : FromUrl[0].string_value) << std::endl;
- }
- else if (!FromHeader.empty()) {
- ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::HEADER;" << std::endl;
- ss << fmt::format("\t\t\targument->parameter_name_ = \"{}\";", FromHeader[0].string_value.empty() ? name : FromHeader[0].string_value) << std::endl;
- }
- else {
- ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::QUERY;" << std::endl;
- ss << fmt::format("\t\t\targument->parameter_name_ = \"{}\";", name) << std::endl;
- }
- }
- }
- else if (type == "robotics::v3::mvc::multipart_value" || type == "v3::mvc::multipart_value" || type == "mvc::multipart_value") {
- ss << "\t\t\targument->argument_type_ = " << type_map["Multipart"] << ";" << std::endl;
- ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::BODY;" << std::endl;
- ss << "\t\t\targument->parameter_name_ = \"\";" << std::endl;
- }
- else if (type.size() > 12 && type.substr(0, 11) == "std::vector") {
- ss << "\t\t\targument->argument_type_ = " << type_map["VecJson"] << ";" << std::endl;
- ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::BODY;" << std::endl;
- ss << "\t\t\targument->parameter_name_ = \"\";" << std::endl;
- }
- else {
- ss << "\t\t\targument->argument_type_ = " << type_map["Json"] << ";" << std::endl;
- ss << "\t\t\targument->from_storage_type_ = robotics::v3::mvc::from_storage_type::BODY;" << std::endl;
- ss << "\t\t\targument->parameter_name_ = \"\";" << std::endl;
- }
- ss << "\t\t\taction->arguments.push_back(argument);" << std::endl;
- ss << "\t\t}" << std::endl;
- return ss.str();
- }
- std::string generate_soap_code() {
- static std::map<std::string, std::string> type_map = {
- {"int","robotics::v3::soap_argument_type::Int"},
- {"std::int64_t","robotics::v3::soap_argument_type::Int64"},
- {"float","robotics::v3::soap_argument_type::Float"},
- {"double","robotics::v3::soap_argument_type::Double"},
- {"long","robotics::v3::soap_argument_type::Long"},
- {"bool","robotics::v3::soap_argument_type::Bool_"},
- {"std::string","robotics::v3::soap_argument_type::String"},
- {"robotics::v3::datetime","robotics::v3::soap_argument_type::DateTime"},
- {"v3::datetime","robotics::v3::soap_argument_type::DateTime"},
- {"datetime","robotics::v3::soap_argument_type::DateTime"}
- };
- std::stringstream ss;
- ss << "\t\t{" << std::endl;
- ss << "\t\t\tstd::shared_ptr<robotics::v3::soap_action_argument> argument(new robotics::v3::soap_action_argument());" << std::endl;
- if (type_map.contains(type)) {
- ss << fmt::format("\t\t\targument->argument_type_ = {};", type_map[type]) << std::endl;
- }
- ss << fmt::format("\t\t\targument->parameter_name_ = \"{}\";", name) << std::endl;
- ss << "\t\t\taction->arguments.push_back(argument);" << std::endl;
- ss << "\t\t}" << std::endl;
- return ss.str();
- }
- private:
- /**
- * @brief 反序列化
- * @param code
- */
- void deserialize(std::string code) {
- std::smatch smatch;
- if (std::regex_search(code, smatch, utils::regex::parameter())) {
- if (smatch.size() == 6) {
- type = smatch[4];
- name = smatch[5];
- for (auto& it : get_attributes(smatch[1])) {
- attributes.push_back(class_attribute_info(it));
- }
- }
- }
- }
- /**
- * @brief 获取特性列表
- * @param code
- * @return
- */
- std::vector<std::string> get_attributes(std::string code) {
- std::vector<std::string> result;
- std::smatch smatch;
- while (std::regex_search(code, smatch, utils::regex::attribute())) {
- if (smatch.size() == 3) {
- result.push_back(smatch[0]);
- }
- code = smatch.suffix();
- }
- return result;
- }
- };
- struct class_method_info {
- class_method_info() {}
- class_method_info(std::string code) :
- content(code) {
- deserialize(code);
- }
- std::string content;
- std::string result;
- std::string name;
- std::string signature;
- std::vector<class_parameter_info> parameters;
- std::vector<class_attribute_info> attributes;
- std::string generate_code() {
- if (parameters.empty()) {
- return fmt::format("method(\"{}\",&{{}}::{})",
- name,
- name);
- }
- else {
- std::vector<std::string> param_names;
- std::vector<std::string> param_types;
- for (auto& it : parameters) {
- param_names.push_back(fmt::format("\"{}\"", it.name));
- param_types.push_back(fmt::format("{}{{{{}}}}", it.type));
- }
- return fmt::format("method(\"{}\",&{{}}::{})(rttr::default_arguments({}),rttr::parameter_names({}))",
- name,
- name,
- utils::string::join(param_types, ","),
- utils::string::join(param_names, ","));
- }
- }
- std::string generate_cntlr_code() {
- std::stringstream ss;
- auto ActionType = utils::attribute::find(attributes, "ActionType");
- auto Method = utils::attribute::find(attributes, "Method");
- auto Authen = utils::attribute::find(attributes, "Authen");
- auto Route = utils::attribute::find(attributes, "Route");
- auto ContentType = utils::attribute::find(attributes, "ContentType");
- auto FileMapping = utils::attribute::find(attributes, "FileMapping");
- ss << "\t{" << std::endl;
- ss << "\t\tstd::shared_ptr<robotics::v3::mvc::controller_action> action(new robotics::v3::mvc::controller_action());" << std::endl;
- for (auto& it : parameters) {
- if (!Method.empty()) {
- ss << it.generate_cntlr_code(Method[0].string_value == "POST" ? "POST" : "GET");
- }
- else {
- ss << it.generate_cntlr_code("GET");
- }
- }
- ss << fmt::format("\t\taction->action_name = \"{}\";", name) << std::endl;
- ss << "\t\taction->parent = controller;" << std::endl;
- if (!Authen.empty()) {
- ss << fmt::format("\t\taction->authen = {};", Authen[0].bool_value ? "true" : "false") << std::endl;
- ss << fmt::format("\t\taction->authen_jump = \"{}\";", Authen[0].string_value) << std::endl;
- }
- else {
- ss << "\t\taction->authen = true;" << std::endl;
- ss << "\t\taction->authen_jump = \"\";" << std::endl;
- }
- if (!ContentType.empty()) {
- ss << fmt::format("\t\taction->content_type = \"{}\";", ContentType[0].string_value.empty() ? "application/x-www-form-urlencoded" : ContentType[0].string_value) << std::endl;
- }
- else {
- ss << "\t\taction->content_type = \"application/x-www-form-urlencoded\";" << std::endl;
- }
- if (!ActionType.empty()) {
- ss << fmt::format("\t\taction->action_type = \"{}\";", ActionType[0].string_value) << std::endl;
- }
- else {
- ss << "\t\taction->action_type = \"\";" << std::endl;
- }
- if (!FileMapping.empty()) {
- ss << fmt::format("\t\taction->file_mapping = \"{}\";", FileMapping[0].string_value) << std::endl;
- }
- else {
- ss << "\t\taction->file_mapping = \"\";" << std::endl;
- }
- if (!Method.empty()) {
- if (Method[0].string_value == "POST") {
- ss << "\t\taction->method = robotics::v3::mvc::http_method::POST;" << std::endl;
- }
- else {
- ss << "\t\taction->method = robotics::v3::mvc::http_method::GET;" << std::endl;
- }
- }
- else {
- ss << "\t\taction->method = robotics::v3::mvc::http_method::GET;" << std::endl;
- }
- if (!Route.empty()) {
- ss << fmt::format("\t\tcontroller->actions[\"{}\"] = action;", Route[0].string_value.empty() ? name : Route[0].string_value) << std::endl;
- }
- else {
- ss << fmt::format("\t\tcontroller->actions[\"{}\"] = action;", name) << std::endl;
- }
- ss << "\t}" << std::endl;
- return ss.str();
- }
- std::string generate_soap_code() {
- auto Method = utils::attribute::find(attributes, "Method");
- std::stringstream ss;
- ss << "\t{" << std::endl;
- ss << "\t\tstd::shared_ptr<robotics::v3::soap_controller_action> action(new robotics::v3::soap_controller_action());" << std::endl;
- for (auto& it : parameters) {
- ss << it.generate_soap_code();
- }
- ss << fmt::format("\t\taction->action_name = \"{}\";", name) << std::endl;
- if (!Method.empty()) {
- ss << fmt::format("\t\tcontroller->actions[\"{}\"] = action;", Method[0].string_value.empty() ? name : Method[0].string_value) << std::endl;
- }
- else {
- ss << fmt::format("\t\tcontroller->actions[\"{}\"] = action;", name) << std::endl;
- }
- ss << "\t}" << std::endl;
- return ss.str();
- }
- private:
- /**
- * @brief 反序列化
- * @param code
- */
- void deserialize(std::string code) {
- std::smatch smatch;
- if (std::regex_search(code, smatch, utils::regex::method())) {
- if (smatch.size() == 5) {
- std::vector<std::string> params;
- result = smatch[2];
- name = smatch[3];
- for (auto& it : get_parameters(smatch[4])) {
- parameters.push_back(class_parameter_info(it));
- params.push_back(parameters[parameters.size() - 1].type);
- }
- for (auto& it : get_attributes(smatch[1])) {
- attributes.push_back(class_attribute_info(it));
- }
- signature = result + "(" + utils::string::join(params) + ")";
- }
- }
- }
- /**
- * @brief 获取特性列表
- * @param code
- * @return
- */
- std::vector<std::string> get_attributes(std::string code) {
- std::vector<std::string> result;
- std::smatch smatch;
- while (std::regex_search(code, smatch, utils::regex::attribute())) {
- if (smatch.size() == 3) {
- result.push_back(smatch[0]);
- }
- code = smatch.suffix();
- }
- return result;
- }
- /**
- * @brief 获取参数列表
- * @param code
- * @return
- */
- std::vector<std::string> get_parameters(std::string code) {
- std::vector<std::string> result;
- std::smatch smatch;
- while (std::regex_search(code, smatch, utils::regex::parameter())) {
- if (smatch.size() == 6) {
- result.push_back(smatch[0]);
- }
- code = smatch.suffix();
- }
- return result;
- }
- };
- struct class_view_info {
- class_view_info() {}
- class_view_info(std::string code, int type) :
- content(code),
- class_type(type) {
- deserialize(code);
- }
- int class_type = 0;
- std::string content;
- std::string type;
- std::string name;
- bool is_tmpl = false;
- std::vector<std::string> tmpl_params;
- std::vector<class_attribute_info> attributes;
- std::vector<class_property_info> propertys;
- std::vector<class_method_info> cntlr_methods;
- std::vector<class_method_info> soap_methods;
- std::pair<std::string, std::string> generate_code() {
- std::stringstream ss;
- std::string funcname = fmt::format("func_{}()", utils::string::generate_hex(16));
- ss << "static void " << funcname << " {" << std::endl;
- if (class_type == 0) {
- auto SqlTable = utils::attribute::find(attributes, "SqlTable");
- auto NoReflect = utils::attribute::find(attributes, "NoReflect");
- auto TemplateType = utils::attribute::find(attributes, "TemplateType");
- if (NoReflect.empty() || (!NoReflect.empty() && !NoReflect[0].bool_value)) {
- if (!is_tmpl) {
- std::vector<std::string> item;
- item.push_back(fmt::format("\trttr::registration::class_<{} {}>(\"{}\").constructor<>()(rttr::detail::as_object{{}})", type, name, SqlTable.empty() ? name : SqlTable[0].string_value));
- for (auto it : propertys) {
- item.push_back(fmt::vformat(it.generate_code(), fmt::make_format_args(name)));
- }
- if (item.size() > 1) {
- ss << utils::string::join(item, ".\n\t\t") << ";" << std::endl;
- }
- }
- else {
- std::vector<std::string> class_propertys;
- for (auto it : propertys) {
- class_propertys.push_back(it.generate_code());
- }
- for (auto it : TemplateType) {
- std::vector<std::string> item;
- std::string tablename = name + "<" + utils::string::join(it.vector_string_value, ",") + ">";
- item.push_back(fmt::format("\trttr::registration::class_<{} {}>(\"{}\").constructor<>()(rttr::detail::as_object{{}})", type, tablename, tablename));
- for (auto it1 : class_propertys) {
- item.push_back(fmt::vformat(it1, fmt::make_format_args(tablename)));
- }
- if (item.size() > 1) {
- ss << utils::string::join(item, ".\n\t\t") << ";" << std::endl;
- }
- }
- }
- }
- }
- else if (class_type == 1) {
- auto NoReflect = utils::attribute::find(attributes, "NoReflect");
- if (NoReflect.empty() || (!NoReflect.empty() && !NoReflect[0].bool_value)) {
- std::vector<std::string> item;
- item.push_back(fmt::format("\trttr::registration::class_<{} {}>(\"{}\").constructor<>()()", type, name, name));
- for (auto it : cntlr_methods) {
- item.push_back(fmt::vformat(it.generate_code(), fmt::make_format_args(name)));
- }
- if (item.size() > 1) {
- ss << utils::string::join(item, ".\n\t\t") << ";" << std::endl;
- }
- }
- ss << "\tstd::shared_ptr<robotics::v3::mvc::controller> controller(new robotics::v3::mvc::controller());" << std::endl;
- for (auto& it : cntlr_methods) {
- ss << it.generate_cntlr_code();
- }
- ss << fmt::format("\tcontroller->controller_name = \"{}\";", name) << std::endl;
- ss << "\trobotics::v3::mvc::ico_controller::attach(controller);" << std::endl;
- }
- else if (class_type == 2) {
- auto NoReflect = utils::attribute::find(attributes, "NoReflect");
- auto Route = utils::attribute::find(attributes, "Route");
- auto Version = utils::attribute::find(attributes, "Version");
- auto Namespace = utils::attribute::find(attributes, "Namespace");
- auto Wsdl = utils::attribute::find(attributes, "Wsdl");
- if (NoReflect.empty() || (!NoReflect.empty() && !NoReflect[0].bool_value)) {
- std::vector<std::string> item;
- item.push_back(fmt::format("\trttr::registration::class_<{} {}>(\"{}\").constructor<>()()", type, name, name));
- for (auto it : soap_methods) {
- item.push_back(fmt::vformat(it.generate_code(), fmt::make_format_args(name)));
- }
- if (item.size() > 1) {
- ss << utils::string::join(item, ".\n\t\t") << ";" << std::endl;
- }
- ss << "\tstd::shared_ptr<robotics::v3::soap_controller> controller(new robotics::v3::soap_controller());" << std::endl;
- for (auto& it : soap_methods) {
- ss << it.generate_soap_code();
- }
- ss << fmt::format("\tcontroller->controller_name = \"{}\";", name) << std::endl;
- if (!Wsdl.empty()) {
- ss << fmt::format("\tcontroller->wsdl = \"{}\";", Wsdl[0].string_value) << std::endl;
- }
- else {
- ss << "\tstatic_assert(false, \"wsdl path error\");" << std::endl;
- }
- if (!Route.empty()) {
- ss << fmt::format("\tcontroller->route = \"{}\";", Route[0].string_value) << std::endl;
- }
- else {
- ss << "\tstatic_assert(false, \"route path error\");" << std::endl;
- }
- if (!Namespace.empty()) {
- ss << fmt::format("\tcontroller->namespace_name = \"{}\";", Namespace[0].string_value) << std::endl;
- }
- else {
- ss << "\tstatic_assert(false, \"namespace path error\");" << std::endl;
- }
- if (!Version.empty()) {
- 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;
- }
- else {
- ss << "\tcontroller->version = robotics::v3::soap_version::VER1_1;" << std::endl;
- }
- ss << "\trobotics::v3::soap_ioc_controller::attach(controller);" << std::endl;
- }
- }
- ss << "}" << std::endl;
- return std::pair(funcname, ss.str());
- }
- private:
- /**
- * @brief
- * @param code
- */
- void deserialize(std::string code) {
- std::smatch smatch;
- if (std::regex_search(code, smatch, utils::regex::class_())) {
- if (smatch.size() == 5) {
- std::string tmp_code = smatch.suffix();
- std::size_t index = tmp_code.find('{');
- if (index != std::string::npos && utils::string::ergodic(tmp_code, index)) {
- tmpl_params = get_tmpl_params(smatch[1]);
- type = smatch[2];
- name = smatch[4];
- is_tmpl = !smatch[1].str().empty();
- for (auto& it : get_attributes(smatch[3])) {
- attributes.push_back(class_attribute_info(it));
- }
- if (class_type == 0) {
- for (auto& it : get_propertys(tmp_code.substr(0, index + 1))) {
- propertys.push_back(class_property_info(it));
- }
- }
- else if (class_type == 1) {
- for (auto& it : get_methods(tmp_code.substr(0, index + 1))) {
- cntlr_methods.push_back(class_method_info(it));
- }
- }
- else if (class_type == 2) {
- for (auto& it : get_methods(tmp_code.substr(0, index + 1))) {
- soap_methods.push_back(class_method_info(it));
- }
- }
- code = smatch.suffix().str().substr(index + 1);
- }
- else {
- code = smatch.suffix();
- }
- }
- else {
- code = smatch.suffix();
- }
- }
- }
- /**
- * @brief 获取特性列表
- * @param code
- * @return
- */
- std::vector<std::string> get_attributes(std::string code) {
- std::vector<std::string> result;
- std::smatch smatch;
- while (std::regex_search(code, smatch, utils::regex::attribute())) {
- if (smatch.size() == 3) {
- result.push_back(smatch[0]);
- }
- code = smatch.suffix();
- }
- return result;
- }
- /**
- * @brief 获取模板参数名称
- * @param code
- * @return
- */
- std::vector<std::string> get_tmpl_params(std::string code) {
- std::vector<std::string> result;
- std::smatch smatch;
- while (std::regex_search(code, smatch, utils::regex::template_())) {
- if (smatch.size() == 2) {
- auto params = utils::string::split(smatch[1]);
- for (auto it : params) {
- it = utils::string::replace(it, "typename", "");
- result.push_back(utils::string::trim(it));
- }
- }
- code = smatch.suffix();
- }
- return result;
- }
- /**
- * @brief 获取属性列表
- * @param code
- * @return
- */
- std::vector<std::string> get_propertys(std::string code) {
- std::vector<std::string> result;
- std::smatch smatch;
- while (std::regex_search(code, smatch, utils::regex::property())) {
- if (smatch.size() == 4) {
- result.push_back(smatch[0]);
- }
- code = smatch.suffix();
- }
- return result;
- }
- /**
- * @brief
- * @param code
- * @return
- */
- std::vector<std::string> get_methods(std::string code) {
- std::vector<std::string> result;
- std::smatch smatch;
- while (std::regex_search(code, smatch, utils::regex::method())) {
- if (smatch.size() == 5) {
- result.push_back(smatch[0]);
- }
- code = smatch.suffix();
- }
- return result;
- }
- };
- struct class_code_info {
- class_code_info() {}
- class_code_info(std::string code, int _type, std::string path, std::string relative_path) :
- content(code),
- type(_type),
- root_directory(path),
- relative_directory(relative_path) {
- deserialize(code);
- }
- //0实体类,1web控制器,2saop控制器
- int type = 0;
- std::string root_directory;
- std::string content;
- std::string relative_directory;
- std::vector<class_view_info> views;
- std::pair<std::vector<std::string>, std::string> generate_code() {
- std::vector<std::string> funclist;
- std::stringstream ss;
- for (auto& it : views) {
- auto view_code = it.generate_code();
- funclist.push_back(view_code.first);
- ss << view_code.second;
- }
- return std::pair(funclist, ss.str());
- }
- private:
- /**
- * @brief
- * @param code
- */
- void deserialize(std::string code) {
- delete_excess(code);
- std::smatch smatch;
- while (std::regex_search(code, smatch, utils::regex::class_())) {
- if (smatch.size() == 5) {
- std::string src = smatch[0];
- std::string tmp_code = smatch.suffix();
- std::size_t index = tmp_code.find('{');
- if (index != std::string::npos && utils::string::ergodic(tmp_code, index)) {
- src += tmp_code.substr(0, index + 1);
- views.push_back(class_view_info(src, type));
- code = smatch.suffix().str().substr(index + 1);
- }
- else {
- code = smatch.suffix();
- }
- }
- else {
- code = smatch.suffix();
- }
- }
- }
- /**
- * @brief 删除注释
- * @param code
- */
- void delete_excess(std::string& code) {
- static std::vector<std::pair<std::string, std::string>> notes = {
- {"/*","*/"},
- {"//","\n"},
- {"#include","\n"},
- {"#pragma", "\n"},
- {"#ifndef", "\n"},
- {"#define", "\n"},
- {"#if", "\n"},
- {"#endif", "\n"}
- };
- for (auto& note : notes) {
- std::size_t begin = 0;
- std::size_t end = 0;
- while ((begin = code.find(note.first, begin)) != std::string::npos && (end = code.find(note.second, begin)) != std::string::npos) {
- if (begin > 0 && code[begin - 1] == ':') {
- begin += note.second.size();
- continue;
- }
- code.erase(begin, end - begin + note.second.size());
- code.insert(code.begin() + begin, ' ');
- begin++;
- }
- }
- }
- };
- class code_analysis {
- public:
- static std::string generate_code(std::string const& path) {
- std::stringstream ss;
- std::vector<std::string> funclist;
- //解析代码
- auto values = code_analysis(path).get_class_code();
- //生成时间
- ss << "//生成时间:" << utils::string::current_time() << std::endl;
- ss << "#pragma once" << std::endl;
- ss << "#include <rttr/registration>" << std::endl;
- ss << "#include <robotics/logger.hpp>" << std::endl;
- //头文件
- for (auto& it : values) {
- ss << "#include \"" << it.relative_directory << "\"" << std::endl;
- }
- ss << std::endl;
- for (auto& it : values) {
- auto view_code = it.generate_code();
- funclist.insert(funclist.end(), view_code.first.begin(), view_code.first.end());
- ss << view_code.second;
- }
- ss << "RTTR_REGISTRATION {" << std::endl;
- ss << "\t" << utils::string::join(funclist, ";\n\t") << ";" << std::endl;
- ss << "}" << std::endl;
- return ss.str();
- }
- static std::vector<class_code_info> get_class_code(std::string const& path) {
- return code_analysis(path).get_class_code();
- }
- private:
- code_analysis(std::string const& path) :
- path_(path) {
- path_ = utils::string::replace(path_, "\\", "/");
- if (path_[path_.size() - 1] != '/') {
- path_ += '/';
- }
- }
- std::vector<class_code_info> get_class_code() {
- std::vector<class_code_info> result;
- auto values = get_models();
- result.insert(result.end(), values.begin(), values.end());
- values = get_controllers();
- result.insert(result.end(), values.begin(), values.end());
- values = get_webservices();
- result.insert(result.end(), values.begin(), values.end());
- return result;
- }
- std::vector<class_code_info> get_models() {
- std::vector<class_code_info> result;
- for (auto& it : get_files(path_ + "models", { ".h" })) {
- result.push_back(class_code_info(get_code(path_ + it), 0, path_, it));
- }
- return result;
- }
- std::vector<class_code_info> get_controllers() {
- std::vector<class_code_info> result;
- for (auto& it : get_files(path_ + "controllers", { ".hpp" })) {
- result.push_back(class_code_info(get_code(path_ + it), 1, path_, it));
- result[result.size() - 1].root_directory = path_;
- result[result.size() - 1].relative_directory = it;
- result[result.size() - 1].type = 1;
- }
- return result;
- }
- std::vector<class_code_info> get_webservices() {
- std::vector<class_code_info> result;
- for (auto& it : get_files(path_ + "webservices", { ".hpp" })) {
- result.push_back(class_code_info(get_code(path_ + it), 2, path_, it));
- result[result.size() - 1].root_directory = path_;
- result[result.size() - 1].relative_directory = it;
- result[result.size() - 1].type = 2;
- }
- return result;
- }
- std::string get_code(std::string const& path) {
- std::ifstream file(path, std::ios::out);
- if (file.is_open()) {
- return std::string((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
- }
- return "";
- }
- std::vector<std::string> get_files(std::string const& path, std::vector<std::string> const& extension) {
- std::vector<std::string> result;
- if (!std::filesystem::is_directory(path)) {
- return result;
- }
- for (auto& itr : std::filesystem::directory_iterator(path)) {
- if (std::filesystem::is_directory(itr.status())) {
- auto values = get_files(itr.path().string(), extension);
- result.insert(result.end(), values.begin(), values.end());
- }
- else {
- if (std::find(extension.begin(), extension.end(), itr.path().extension()) != extension.end()) {
- std::string tmp = itr.path().string();
- tmp = utils::string::replace(tmp, "\\", "/");
- tmp = utils::string::replace(tmp, path_, "");
- result.push_back(tmp);
- }
- }
- }
- return result;
- }
- private:
- std::string path_;
- };
- }
|