|
@@ -1,1368 +1,1145 @@
|
|
|
-#ifndef __CODE_GENERATOR_CODE_ANALYSIS_H__
|
|
|
-#define __CODE_GENERATOR_CODE_ANALYSIS_H__
|
|
|
-
|
|
|
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
|
|
|
#pragma once
|
|
|
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
|
|
|
-
|
|
|
#include <iostream>
|
|
|
#include <filesystem>
|
|
|
#include <regex>
|
|
|
+#include <map>
|
|
|
+#include <any>
|
|
|
+#include <variant>
|
|
|
#include <fstream>
|
|
|
-#include "../robot/robotics/utils.hpp"
|
|
|
-using namespace robotics;
|
|
|
-
|
|
|
-struct file_info {
|
|
|
- /**
|
|
|
- * @brief 路径
|
|
|
- */
|
|
|
- std::string file_path;
|
|
|
- /**
|
|
|
- * @brief 代码
|
|
|
- */
|
|
|
- std::vector<std::string> content;
|
|
|
- /**
|
|
|
- * @brief 类型 0控制器 1实体类 2soap
|
|
|
- */
|
|
|
- int class_type = 0;
|
|
|
-};
|
|
|
+#include <chrono>
|
|
|
+#include <random>
|
|
|
+#include <fmt/format.h>
|
|
|
|
|
|
-struct PropertyInfo {
|
|
|
- /**
|
|
|
- * @brief 类型名称
|
|
|
- */
|
|
|
- std::string type_name;
|
|
|
- /**
|
|
|
- * @brief 属性名称
|
|
|
- */
|
|
|
- std::string prop_name;
|
|
|
- /**
|
|
|
- * @brief json字段名称
|
|
|
- */
|
|
|
- std::string json_name;
|
|
|
- /**
|
|
|
- * @brief 数据库字段名称
|
|
|
- */
|
|
|
- std::string sql_name;
|
|
|
- /**
|
|
|
- * @brief excel字段名称
|
|
|
- */
|
|
|
- std::string excel_name;
|
|
|
- /**
|
|
|
- * @brief 不序列化json 默认false
|
|
|
- */
|
|
|
- bool no_json = false;
|
|
|
- /**
|
|
|
- * @brief 不创建数据库字段 默认false
|
|
|
- */
|
|
|
- bool no_sql = false;
|
|
|
- /**
|
|
|
- * @brief 不导出excel字段 默认false
|
|
|
- */
|
|
|
- bool no_excel = false;
|
|
|
- /**
|
|
|
- * @brief 字段索引
|
|
|
- */
|
|
|
- bool sql_key = false;
|
|
|
- /**
|
|
|
- * @brief 二进制序列化
|
|
|
- */
|
|
|
- bool no_archive = false;
|
|
|
-};
|
|
|
-
|
|
|
-struct ParameterInfo {
|
|
|
- /**
|
|
|
- * @brief 参数名称
|
|
|
- */
|
|
|
- std::string name;
|
|
|
- /**
|
|
|
- * @brief 参数类型
|
|
|
- */
|
|
|
- std::string type;
|
|
|
- /**
|
|
|
- * @brief 参数名称
|
|
|
- */
|
|
|
- std::string parameter_name;
|
|
|
- /**
|
|
|
- * @brief 类型名称
|
|
|
- */
|
|
|
- std::string argument_type = "robotics::v3::mvc::argument_type::Binary";
|
|
|
- /**
|
|
|
- * @brief 提取位置 QUERY Body Header
|
|
|
- */
|
|
|
- std::string from_storage_type = "robotics::v3::mvc::from_storage_type::QUERY";
|
|
|
-};
|
|
|
-
|
|
|
-struct MethodInfo {
|
|
|
- /**
|
|
|
- * @brief 身份验证
|
|
|
- */
|
|
|
- bool authen = true;
|
|
|
- /**
|
|
|
- * @brief 未登录跳转
|
|
|
- */
|
|
|
- std::string authen_jump;
|
|
|
-
|
|
|
- /**
|
|
|
- * @brief
|
|
|
- */
|
|
|
- std::string method = "robotics::v3::mvc::http_method::GET";
|
|
|
- /**
|
|
|
- * @brief
|
|
|
- */
|
|
|
- std::string content_type = "application/x-www-form-urlencoded";
|
|
|
- /**
|
|
|
- * @brief
|
|
|
- */
|
|
|
- std::string action_type;
|
|
|
- /**
|
|
|
- * @brief
|
|
|
- */
|
|
|
- std::string file_mapping;
|
|
|
- /**
|
|
|
- * @brief
|
|
|
- */
|
|
|
- std::string route;
|
|
|
- /**
|
|
|
- * @brief
|
|
|
- */
|
|
|
- std::string name;
|
|
|
- /**
|
|
|
- * @brief 函数签名
|
|
|
- */
|
|
|
- std::string signature;
|
|
|
- /**
|
|
|
- * @brief 参数
|
|
|
- */
|
|
|
- std::vector<ParameterInfo> parameters;
|
|
|
-};
|
|
|
-
|
|
|
-struct SoapParameterInfo {
|
|
|
- /**
|
|
|
- * @brief 类型
|
|
|
- */
|
|
|
- std::string type = "std::string";
|
|
|
- /**
|
|
|
- * @brief 参数类型
|
|
|
- */
|
|
|
- std::string argument_type = "robotics::v3::mvc::soap_argument_type::String";
|
|
|
- /**
|
|
|
- * @brief 参数名称
|
|
|
- */
|
|
|
- std::string parameter_name = "value";
|
|
|
-};
|
|
|
-
|
|
|
-struct soap_method_info {
|
|
|
- /**
|
|
|
- * @brief 方法名称
|
|
|
- */
|
|
|
- std::string name;
|
|
|
- /**
|
|
|
- * @brief 路由方法名称
|
|
|
- */
|
|
|
- std::string action_name;
|
|
|
- /**
|
|
|
- * @brief 函数签名
|
|
|
- */
|
|
|
- std::string signature;
|
|
|
- /**
|
|
|
- * @brief 参数
|
|
|
- */
|
|
|
- std::vector<SoapParameterInfo> parameters;
|
|
|
-};
|
|
|
-
|
|
|
-struct class_view_info {
|
|
|
- /**
|
|
|
- * @brief 0:控制器 1:实体类 2:soap
|
|
|
- */
|
|
|
- int class_type = 0;
|
|
|
- /**
|
|
|
- * @brief 是否是模板
|
|
|
- */
|
|
|
- bool is_template = false;
|
|
|
- /**
|
|
|
- * @brief 模板类型列表
|
|
|
- */
|
|
|
- std::vector<std::string> template_types;
|
|
|
- /**
|
|
|
- * @brief 模板参数列表
|
|
|
- */
|
|
|
- std::vector<std::string> template_parameters;
|
|
|
- /**
|
|
|
- * @brief 类名称
|
|
|
- */
|
|
|
- std::string class_name;
|
|
|
- /**
|
|
|
- * @brief 数据库表名称
|
|
|
- */
|
|
|
- std::string sql_table_name;
|
|
|
- /**
|
|
|
- * @brief 属性列表
|
|
|
- */
|
|
|
- std::vector<PropertyInfo> propertys;
|
|
|
- /**
|
|
|
- * @brief 控制器列表
|
|
|
- */
|
|
|
- std::vector<MethodInfo> methods;
|
|
|
- /**
|
|
|
- * @brief soap 方法列表
|
|
|
- */
|
|
|
- std::vector<soap_method_info> soap_methods;
|
|
|
- /**
|
|
|
- * @brief soap版本
|
|
|
- */
|
|
|
- std::string soap_version = "1.1";
|
|
|
- /**
|
|
|
- * @brief soap命名空间
|
|
|
- */
|
|
|
- std::string soap_namepsace = "http://tempuri.org/";
|
|
|
- /**
|
|
|
- * @brief soap路由
|
|
|
- */
|
|
|
- std::string soap_route;
|
|
|
- /**
|
|
|
- * @brief soap wsdl文件
|
|
|
- */
|
|
|
- std::string soap_wsdl;
|
|
|
+namespace analysis {
|
|
|
+ struct class_attribute_info;
|
|
|
/**
|
|
|
- * @brief 头文件
|
|
|
- */
|
|
|
- std::string include;
|
|
|
- /**
|
|
|
- * @brief 反射
|
|
|
- */
|
|
|
- bool is_reflect = true;
|
|
|
-};
|
|
|
-
|
|
|
-class code_analysis_core {
|
|
|
-public:
|
|
|
- static std::vector<class_view_info> getClassView(std::filesystem::path path) {
|
|
|
- return code_analysis_core(path).getClassView();
|
|
|
- }
|
|
|
-protected:
|
|
|
- code_analysis_core(std::filesystem::path path) :
|
|
|
- _path(path) {
|
|
|
- }
|
|
|
-private:
|
|
|
- std::vector<class_view_info> getClassView() {
|
|
|
- std::vector<class_view_info> result;
|
|
|
- auto fileInfos = getiFileInfo();
|
|
|
- //控制器
|
|
|
- for (auto& it : fileInfos) {
|
|
|
- if (it.class_type != 0)
|
|
|
- continue;
|
|
|
-
|
|
|
- for (auto code : it.content) {
|
|
|
- std::regex pattern("class[ \r\n\t]{1,30}([a-zA-Z_0-9]{1,100})");
|
|
|
- std::smatch smatch;
|
|
|
- if (std::regex_search(code, smatch, pattern)) {
|
|
|
- if (smatch.size() == 2) {
|
|
|
- class_view_info add;
|
|
|
- add.include = it.file_path;
|
|
|
- add.class_type = 0;
|
|
|
- add.class_name = smatch[1];
|
|
|
- add.methods = getMethods(smatch.suffix());
|
|
|
- result.push_back(add);
|
|
|
- }
|
|
|
+ * @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;
|
|
|
}
|
|
|
- }
|
|
|
- //实体类
|
|
|
- for (auto& it : fileInfos) {
|
|
|
- if (it.class_type != 1)
|
|
|
- continue;
|
|
|
-
|
|
|
- for (auto code : it.content) {
|
|
|
-
|
|
|
- //普通模板结构体
|
|
|
- {
|
|
|
- std::regex pattern("template[ \r\n\t]{0,30}<([\\s\\S]*?)>[ \r\n\t]{0,30}struct[ \r\n\t]{1,30}([a-zA-Z_0-9]{1,100})");
|
|
|
- std::smatch smatch;
|
|
|
- if (std::regex_search(code, smatch, pattern)) {
|
|
|
- if (smatch.size() == 3) {
|
|
|
- class_view_info add;
|
|
|
- add.include = it.file_path;
|
|
|
- add.class_type = 1;
|
|
|
- add.class_name = smatch[2];
|
|
|
- add.is_template = true;
|
|
|
- add.sql_table_name = smatch[2];
|
|
|
- auto templteTypeList = v3::utils::split(smatch[1], ",");
|
|
|
- for (auto& tempType : templteTypeList) {
|
|
|
- auto tempValue = v3::utils::split(tempType, " ");
|
|
|
- if (tempValue.size() == 2) {
|
|
|
- add.template_types.push_back(v3::utils::trim(tempValue[1]));
|
|
|
- }
|
|
|
- }
|
|
|
- add.propertys = getPropertys(smatch.suffix());
|
|
|
- result.push_back(add);
|
|
|
- code = smatch.suffix();
|
|
|
- }
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * @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::regex pattern("template[ \r\n\t]{0,30}<([\\s\\S]*?)>[ \r\n\t]{0,30}struct[ \r\n\t]{0,30}(\\[\\[[\\s\\S]*?\\]\\])[ \r\n\t]{0,30}([a-zA-Z_0-9]{1,100})[ \r\n\t]{0,30}\\{");
|
|
|
- std::smatch smatch;
|
|
|
- if (std::regex_search(code, smatch, pattern)) {
|
|
|
- if (smatch.size() == 4) {
|
|
|
- class_view_info add;
|
|
|
- add.include = it.file_path;
|
|
|
- add.class_type = 1;
|
|
|
- add.class_name = smatch[3];
|
|
|
- add.is_template = true;
|
|
|
- auto templteTypeList = v3::utils::split(smatch[1], ",");
|
|
|
- for (auto& tempType : templteTypeList) {
|
|
|
- auto tempValue = v3::utils::split(tempType, " ");
|
|
|
- if (tempValue.size() == 2) {
|
|
|
- add.template_types.push_back(v3::utils::trim(tempValue[1]));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- getTemplateParameter(smatch[2], add.template_types.size(), add);
|
|
|
-
|
|
|
- add.sql_table_name = add.sql_table_name.empty() ? add.class_name : add.sql_table_name;
|
|
|
- add.propertys = getPropertys("{" + smatch.suffix().str());
|
|
|
- result.push_back(add);
|
|
|
- code = smatch.suffix();
|
|
|
- }
|
|
|
- }
|
|
|
+ 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);
|
|
|
}
|
|
|
- //普通结构体
|
|
|
- {
|
|
|
- std::regex pattern("struct[ \r\n\t]{1,30}([a-zA-Z_0-9]{1,100})");
|
|
|
- std::smatch smatch;
|
|
|
- if (std::regex_search(code, smatch, pattern)) {
|
|
|
- if (smatch.size() == 2) {
|
|
|
- class_view_info add;
|
|
|
- add.include = it.file_path;
|
|
|
- add.class_type = 1;
|
|
|
- add.class_name = smatch[1];
|
|
|
- add.sql_table_name = smatch[1];
|
|
|
- add.propertys = getPropertys(smatch.suffix());
|
|
|
- result.push_back(add);
|
|
|
- code = smatch.suffix();
|
|
|
- }
|
|
|
+ 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());
|
|
|
}
|
|
|
- }
|
|
|
- //带反射特性结构体
|
|
|
- {
|
|
|
- std::regex pattern("struct[ \r\n\t]{0,30}\\[\\[NoReflect\\]\\][ \r\n\t]{0,30}([a-zA-Z_0-9]{1,100})");
|
|
|
- std::smatch smatch;
|
|
|
- if (std::regex_search(code, smatch, pattern)) {
|
|
|
- if (smatch.size() == 2) {
|
|
|
- class_view_info add;
|
|
|
- add.include = it.file_path;
|
|
|
- add.class_type = 1;
|
|
|
- add.class_name = smatch[1];
|
|
|
- add.sql_table_name = smatch[1].length() == 0 ? add.class_name : smatch[1];
|
|
|
- add.propertys = getPropertys(smatch.suffix());
|
|
|
- add.is_reflect = false;
|
|
|
- result.push_back(add);
|
|
|
- code = smatch.suffix();
|
|
|
- }
|
|
|
+ else {
|
|
|
+ result += c + values[0];
|
|
|
+ values.erase(values.begin());
|
|
|
}
|
|
|
}
|
|
|
- //带数据库特性结构体
|
|
|
- {
|
|
|
- std::regex pattern("struct[ \r\n\t]{0,30}\\[\\[SqlTable\\(\"(.*?)\"\\)\\]\\][ \r\n\t]{0,30}([a-zA-Z_0-9]{1,100})");
|
|
|
- std::smatch smatch;
|
|
|
- if (std::regex_search(code, smatch, pattern)) {
|
|
|
- if (smatch.size() == 3) {
|
|
|
- class_view_info add;
|
|
|
- add.include = it.file_path;
|
|
|
- add.class_type = 1;
|
|
|
- add.class_name = smatch[2];
|
|
|
- add.sql_table_name = smatch[1].length() == 0 ? add.class_name : smatch[1];
|
|
|
- add.propertys = getPropertys(smatch.suffix());
|
|
|
- result.push_back(add);
|
|
|
- code = smatch.suffix();
|
|
|
- }
|
|
|
- }
|
|
|
+ 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;
|
|
|
}
|
|
|
- //带数据库反射特性结构体
|
|
|
- {
|
|
|
- std::regex pattern("struct[ \r\n\t]{0,30}\\[\\[NoReflect\\]\\][ \r\n\t]{0,30}\\[\\[SqlTable\\(\"(.*?)\"\\)\\]\\][ \r\n\t]{0,30}([a-zA-Z_0-9]{1,100})");
|
|
|
- std::smatch smatch;
|
|
|
- if (std::regex_search(code, smatch, pattern)) {
|
|
|
- if (smatch.size() == 3) {
|
|
|
- class_view_info add;
|
|
|
- add.include = it.file_path;
|
|
|
- add.class_type = 1;
|
|
|
- add.class_name = smatch[2];
|
|
|
- add.sql_table_name = smatch[1].length() == 0 ? add.class_name : smatch[1];
|
|
|
- add.propertys = getPropertys(smatch.suffix());
|
|
|
- add.is_reflect = false;
|
|
|
- result.push_back(add);
|
|
|
- code = smatch.suffix();
|
|
|
- }
|
|
|
+ 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;
|
|
|
}
|
|
|
- }
|
|
|
- //soap
|
|
|
- for (auto& it : fileInfos) {
|
|
|
- if (it.class_type != 2)
|
|
|
- continue;
|
|
|
-
|
|
|
- for (auto code : it.content) {
|
|
|
- std::regex pattern("class[ \r\n\t]{1,30}\\[\\[(.*?)\\]\\][ \r\n\t]{1,30}\\[\\[(.*?)\\]\\][ \r\n\t]{1,30}\\[\\[(.*?)\\]\\][ \r\n\t]{1,30}\\[\\[(.*?)\\]\\][ \r\n\t]{1,30}([a-zA-Z_0-9]{1,100})");
|
|
|
- std::smatch smatch;
|
|
|
- if (std::regex_search(code, smatch, pattern)) {
|
|
|
- if (smatch.size() == 6) {
|
|
|
- class_view_info add;
|
|
|
- add.include = it.file_path;
|
|
|
- add.class_type = 2;
|
|
|
- getSoapAttribute(smatch[1], add);
|
|
|
- getSoapAttribute(smatch[2], add);
|
|
|
- getSoapAttribute(smatch[3], add);
|
|
|
- getSoapAttribute(smatch[4], add);
|
|
|
- add.class_name = smatch[5];
|
|
|
-
|
|
|
- add.soap_methods = getSoapMethods(smatch.suffix());
|
|
|
- result.push_back(add);
|
|
|
+ /**
|
|
|
+ * @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;
|
|
|
}
|
|
|
- }
|
|
|
- std::string rootPath = _path.string();
|
|
|
-
|
|
|
- rootPath = v3::utils::replace(rootPath, "\\", "/");
|
|
|
-
|
|
|
- if (rootPath[rootPath.size() - 1] != '/') {
|
|
|
- rootPath += "/";
|
|
|
- }
|
|
|
-
|
|
|
- for (auto& it : result) {
|
|
|
- it.include = v3::utils::replace(it.include, rootPath, "");
|
|
|
- }
|
|
|
-
|
|
|
- return result;
|
|
|
- }
|
|
|
- std::vector<file_info> getiFileInfo() {
|
|
|
- std::vector<file_info> result;
|
|
|
-
|
|
|
- auto controllerFiles = getControllerFiles();
|
|
|
-
|
|
|
- auto modelFiles = getModelsFiles();
|
|
|
-
|
|
|
- auto webServiceFiles = getWebServicesFiles();
|
|
|
-
|
|
|
- for (auto& item : controllerFiles) {
|
|
|
- file_info add;
|
|
|
- //获取代码
|
|
|
- std::string code = getCode(item);
|
|
|
- //剔除无用代码
|
|
|
- eliminateNotes(code);
|
|
|
- //
|
|
|
- add.class_type = 0;
|
|
|
- add.content = getStructContent(code);
|
|
|
- for (auto& it : add.content) {
|
|
|
- eliminateController(it);
|
|
|
+ /**
|
|
|
+ * @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);
|
|
|
}
|
|
|
-
|
|
|
- add.file_path = v3::utils::replace(item.string(), "\\", "/");
|
|
|
- result.push_back(add);
|
|
|
- }
|
|
|
-
|
|
|
- for (auto& item : modelFiles) {
|
|
|
- file_info add;
|
|
|
- //获取代码
|
|
|
- std::string code = getCode(item);
|
|
|
- //剔除无用代码
|
|
|
- eliminateNotes(code);
|
|
|
- //
|
|
|
- add.class_type = 1;
|
|
|
- add.content = getStructContent(code);
|
|
|
- add.file_path = v3::utils::replace(item.string(), "\\", "/");
|
|
|
- result.push_back(add);
|
|
|
- }
|
|
|
-
|
|
|
- for (auto& item : webServiceFiles) {
|
|
|
- file_info add;
|
|
|
- //获取代码
|
|
|
- std::string code = getCode(item);
|
|
|
- //剔除无用代码
|
|
|
- eliminateNotes(code);
|
|
|
- //
|
|
|
- add.class_type = 2;
|
|
|
- add.content = getStructContent(code);
|
|
|
- for (auto& it : add.content) {
|
|
|
- eliminateWebService(it);
|
|
|
- }
|
|
|
- add.file_path = v3::utils::replace(item.string(), "\\", "/");
|
|
|
- result.push_back(add);
|
|
|
- }
|
|
|
-
|
|
|
- return result;
|
|
|
- }
|
|
|
- std::vector<std::filesystem::path> getControllerFiles() {
|
|
|
- std::filesystem::path controllersPath = _path;
|
|
|
- controllersPath /= "controllers";
|
|
|
- std::vector<std::filesystem::path> files;
|
|
|
- getFiles(controllersPath, { ".hpp" }, files);
|
|
|
- return files;
|
|
|
- }
|
|
|
- std::vector<std::filesystem::path> getModelsFiles() {
|
|
|
- std::filesystem::path modelsPath = _path;
|
|
|
- modelsPath /= "models";
|
|
|
- std::vector<std::filesystem::path> files;
|
|
|
- getFiles(modelsPath, { ".h" }, files);
|
|
|
- return files;
|
|
|
- }
|
|
|
- std::vector<std::filesystem::path> getWebServicesFiles() {
|
|
|
- std::filesystem::path webServicesPath = _path;
|
|
|
- webServicesPath /= "webservices";
|
|
|
- std::vector<std::filesystem::path> files;
|
|
|
- getFiles(webServicesPath, { ".hpp" }, files);
|
|
|
- return files;
|
|
|
- }
|
|
|
-
|
|
|
- void getFiles(std::filesystem::path path, std::vector<std::string> extension, std::vector<std::filesystem::path>& files)
|
|
|
- {
|
|
|
- if (!std::filesystem::is_directory(path)) {
|
|
|
- return;
|
|
|
- }
|
|
|
- for (auto& itr : std::filesystem::directory_iterator(path))
|
|
|
- {
|
|
|
- if (std::filesystem::is_directory(itr.status()))
|
|
|
- {
|
|
|
- getFiles(itr.path(), extension, files);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- if (std::find(extension.begin(), extension.end(), itr.path().extension()) != extension.end()) {
|
|
|
- files.push_back(itr.path());
|
|
|
+ /**
|
|
|
+ * @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();
|
|
|
}
|
|
|
- }
|
|
|
- }
|
|
|
- std::string getCode(std::filesystem::path 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 "";
|
|
|
- }
|
|
|
- void eliminateNotes(std::string& code) {
|
|
|
- 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;
|
|
|
+ /**
|
|
|
+ * @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]);
|
|
|
}
|
|
|
- code.erase(begin, end - begin + note.second.size());
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
- void eliminateController(std::string& code) {
|
|
|
- std::string tmpCode = code;
|
|
|
- std::regex pattern("WebResponse[ \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})");
|
|
|
- std::smatch smatch;
|
|
|
- while (std::regex_search(tmpCode, smatch, pattern)) {
|
|
|
- std::string value = smatch[0];
|
|
|
-
|
|
|
- std::size_t pos = code.find(value);
|
|
|
-
|
|
|
- if (pos == std::string::npos)
|
|
|
- break;
|
|
|
- pos += value.size();
|
|
|
- int begin = 0;
|
|
|
- int end = 0;
|
|
|
-
|
|
|
- for (std::size_t i = pos; i < code.size(); ++i) {
|
|
|
-
|
|
|
- if (code[i] == '"') {
|
|
|
- int tmpBegin = 0;
|
|
|
- for (std::size_t i1 = i; i1 < code.size(); ++i1) {
|
|
|
- if (code[i1] == '"') {
|
|
|
- tmpBegin++;
|
|
|
- }
|
|
|
- code.erase(i1, 1);
|
|
|
- i1--;
|
|
|
- if (tmpBegin == 2) {
|
|
|
- break;
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * @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));
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
- if (code[i] == '{') {
|
|
|
- begin++;
|
|
|
- }
|
|
|
- else if (code[i] == '}') {
|
|
|
- end++;
|
|
|
- }
|
|
|
- code.erase(i, 1);
|
|
|
- i--;
|
|
|
- if (begin > 0 && end == begin) {
|
|
|
- code.insert(code.begin() + i, ';');
|
|
|
- break;
|
|
|
+ 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);
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
+ }
|
|
|
+ };
|
|
|
|
|
|
- tmpCode = smatch.suffix();
|
|
|
+ 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;
|
|
|
}
|
|
|
- void eliminateWebService(std::string& code) {
|
|
|
- std::string tmpCode = code;
|
|
|
- std::regex pattern("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})");
|
|
|
- std::smatch smatch;
|
|
|
- while (std::regex_search(tmpCode, smatch, pattern)) {
|
|
|
- std::string value = smatch[0];
|
|
|
-
|
|
|
- std::size_t pos = code.find(value);
|
|
|
-
|
|
|
- if (pos == std::string::npos)
|
|
|
- break;
|
|
|
- pos += value.size();
|
|
|
- int begin = 0;
|
|
|
- int end = 0;
|
|
|
-
|
|
|
- for (std::size_t i = pos; i < code.size(); ++i) {
|
|
|
|
|
|
- if (code[i] == '"') {
|
|
|
- int tmpBegin = 0;
|
|
|
- for (std::size_t i1 = i; i1 < code.size(); ++i1) {
|
|
|
- if (code[i1] == '"') {
|
|
|
- tmpBegin++;
|
|
|
- }
|
|
|
- code.erase(i1, 1);
|
|
|
- i1--;
|
|
|
- if (tmpBegin == 2) {
|
|
|
- break;
|
|
|
- }
|
|
|
+ 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));
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
- if (code[i] == '{') {
|
|
|
- begin++;
|
|
|
- }
|
|
|
- else if (code[i] == '}') {
|
|
|
- end++;
|
|
|
- }
|
|
|
- code.erase(i, 1);
|
|
|
- i--;
|
|
|
- if (begin > 0 && end == begin) {
|
|
|
- code.insert(code.begin() + i, ';');
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
- tmpCode = smatch.suffix();
|
|
|
}
|
|
|
- }
|
|
|
- std::vector<std::string> getStructContent(std::string code) {
|
|
|
- std::vector<std::string> result;
|
|
|
-
|
|
|
- auto func = [](std::string reg, std::string code) {
|
|
|
+ /**
|
|
|
+ * @brief 获取特性列表
|
|
|
+ * @param code
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ std::vector<std::string> get_attributes(std::string code) {
|
|
|
std::vector<std::string> result;
|
|
|
- std::regex pattern(reg);
|
|
|
std::smatch smatch;
|
|
|
- while (std::regex_search(code, smatch, pattern)) {
|
|
|
- std::string structContent = smatch[0];
|
|
|
- std::size_t pos = code.find(structContent);
|
|
|
- if (pos == std::string::npos)
|
|
|
- break;
|
|
|
-
|
|
|
- int begin = 0;
|
|
|
- int end = 0;
|
|
|
- std::string content;
|
|
|
- for (int i = pos; i < code.size(); ++i) {
|
|
|
- content += code[i];
|
|
|
- if (code[i] == '{') {
|
|
|
- begin++;
|
|
|
- }
|
|
|
- else if (code[i] == '}') {
|
|
|
- end++;
|
|
|
- }
|
|
|
- if (begin > 0 && begin == end) {
|
|
|
- break;
|
|
|
- }
|
|
|
+ while (std::regex_search(code, smatch, utils::regex::attribute())) {
|
|
|
+ if (smatch.size() == 3) {
|
|
|
+ result.push_back(smatch[0]);
|
|
|
}
|
|
|
- result.push_back(content);
|
|
|
-
|
|
|
code = smatch.suffix();
|
|
|
}
|
|
|
-
|
|
|
return result;
|
|
|
- };
|
|
|
-
|
|
|
- std::vector<std::string> regList;
|
|
|
- //普通模板结构体
|
|
|
- regList.push_back("template[ \r\n\t]{0,30}<[\\s\\S]*?>[ \r\n\t]{0,30}struct[ \r\n\t]{1,30}[a-zA-Z_0-9]{1,100}");
|
|
|
- //带特性模板结构体
|
|
|
- regList.push_back("template[ \r\n\t]{0,30}<[\\s\\S]*?>[ \r\n\t]{0,30}struct[ \r\n\t]{0,30}\\[\\[[\\s\\S]*?\\]\\][ \r\n\t]{0,30}[a-zA-Z_0-9]{1,100}[ \r\n\t]{0,30}\\{");
|
|
|
- //普通结构体
|
|
|
- regList.push_back("struct[ \r\n\t]{1,30}[a-zA-Z_0-9]{1,100}");
|
|
|
- //带特性结构体
|
|
|
- regList.push_back("struct[ \r\n\t]{0,30}\\[\\[NoReflect\\]\\][ \r\n\t]{0,30}[a-zA-Z_0-9]{1,100}");
|
|
|
- //带特性结构体
|
|
|
- regList.push_back("struct[ \r\n\t]{0,30}\\[\\[SqlTable\\(\".*?\"\\)\\]\\][ \r\n\t]{0,30}[a-zA-Z_0-9]{1,100}");
|
|
|
- //带特性结构体
|
|
|
- regList.push_back("struct[ \r\n\t]{0,30}\\[\\[NoReflect\\]\\][ \r\n\t]{0,30}\\[\\[SqlTable\\(\".*?\"\\)\\]\\][ \r\n\t]{0,30}[a-zA-Z_0-9]{1,100}");
|
|
|
- //控制器
|
|
|
- regList.push_back("class[ \r\n\t]{1,30}[a-zA-Z_0-9]{1,200}");
|
|
|
- //soap
|
|
|
- regList.push_back("class[ \r\n\t]{1,30}\\[\\[.*?\\]\\][ \r\n\t]{1,30}\\[\\[.*?\\]\\][ \r\n\t]{1,30}\\[\\[.*?\\]\\][ \r\n\t]{1,30}\\[\\[.*?\\]\\][ \r\n\t]{1,30}[a-zA-Z_0-9]{1,100}");
|
|
|
-
|
|
|
- std::string tmpCode = code;
|
|
|
- for (auto& it : regList) {
|
|
|
- auto values = func(it, tmpCode);
|
|
|
-
|
|
|
- for (auto& item : values) {
|
|
|
- std::size_t pos = 0;
|
|
|
- if ((pos = tmpCode.find(item)) != std::string::npos) {
|
|
|
- tmpCode.erase(pos, item.size());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- result.insert(result.end(), values.begin(), values.end());
|
|
|
- }
|
|
|
- return result;
|
|
|
- }
|
|
|
- void getTemplateParameter(std::string code, int count, class_view_info& result) {
|
|
|
-
|
|
|
- auto attributes = v3::utils::split(code, "]]");
|
|
|
-
|
|
|
- for (auto& it : attributes) {
|
|
|
- std::size_t begin = 0;
|
|
|
- std::size_t end = 0;
|
|
|
- //TemplateType
|
|
|
- if (it.find("TemplateType") != std::string::npos && (begin = it.find("\"")) != std::string::npos && (end = it.rfind("\"")) != std::string::npos) {
|
|
|
- std::string value = it.substr(begin, end - begin + 1);
|
|
|
- auto values = v3::utils::split(value, ",");
|
|
|
- if (values.size() != count)
|
|
|
- continue;
|
|
|
-
|
|
|
- std::vector<std::string> addItem;
|
|
|
-
|
|
|
- for (auto temp : values) {
|
|
|
-
|
|
|
- if ((begin = temp.find("\"")) != std::string::npos && (end = temp.rfind("\"")) != std::string::npos) {
|
|
|
-
|
|
|
- if (begin == end)
|
|
|
- continue;
|
|
|
- addItem.push_back(temp.substr(begin + 1, end - begin - 1));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (addItem.size() != count)
|
|
|
- continue;
|
|
|
-
|
|
|
- result.template_parameters.push_back(v3::utils::format("{}", v3::utils::join(addItem, ",")));
|
|
|
- }
|
|
|
- //SqlTable
|
|
|
- else if (it.find("SqlTable") != std::string::npos && (begin = it.find("\"")) != std::string::npos && (end = it.rfind("\"")) != std::string::npos) {
|
|
|
- result.sql_table_name = it.substr(begin + 1, end - begin - 1);
|
|
|
- }
|
|
|
}
|
|
|
-
|
|
|
- }
|
|
|
- //获取属性
|
|
|
- std::vector<PropertyInfo> getPropertys(std::string code) {
|
|
|
- std::vector<PropertyInfo> result;
|
|
|
- code.erase(code.find("{"), 1);
|
|
|
- code.erase(code.rfind("}"), 1);
|
|
|
-
|
|
|
- std::vector<std::string> propertyCodes = v3::utils::split(code, ";");
|
|
|
-
|
|
|
- for (auto& prop : propertyCodes) {
|
|
|
- PropertyInfo add;
|
|
|
- //提取特性
|
|
|
- {
|
|
|
- std::regex pattern("\\[\\[(.*?)\\]\\]");
|
|
|
- std::smatch smatch;
|
|
|
- while (std::regex_search(prop, smatch, pattern)) {
|
|
|
- std::string attribute = smatch[1];
|
|
|
-
|
|
|
- std::string Json = "Json";
|
|
|
- std::string NoJson = "NoJson";
|
|
|
- std::string Sql = "Sql";
|
|
|
- std::string NoSql = "NoSql";
|
|
|
- std::string SqlKey = "SqlKey";
|
|
|
- std::string Excel = "Excel";
|
|
|
- std::string NoExcel = "NoExcel";
|
|
|
- std::string NoArchive = "NoArchive";
|
|
|
-
|
|
|
- if (attribute.size() > Json.size() && attribute.substr(0, Json.size()) == Json) {
|
|
|
- auto values = v3::utils::split(attribute, "\"");
|
|
|
- if (values.size() == 3) {
|
|
|
- add.json_name = values[1];
|
|
|
- std::size_t pos = values[2].find("false");
|
|
|
- add.no_json = pos != std::string::npos;
|
|
|
- }
|
|
|
+ };
|
|
|
+
|
|
|
+ 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 (attribute.size() > NoJson.size() && attribute.substr(0, NoJson.size()) == NoJson) {
|
|
|
- attribute = v3::utils::to_upper(attribute);
|
|
|
- if (attribute.find("TRUE") != std::string::npos) {
|
|
|
- add.no_json = true;
|
|
|
- }
|
|
|
+ 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 (attribute.size() > SqlKey.size() && attribute.substr(0, SqlKey.size()) == SqlKey) {
|
|
|
- attribute = v3::utils::to_upper(attribute);
|
|
|
- if (attribute.find("TRUE") != std::string::npos) {
|
|
|
- add.sql_key = true;
|
|
|
- }
|
|
|
+ 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 if (attribute.size() > Sql.size() && attribute.substr(0, Sql.size()) == Sql) {
|
|
|
- auto values = v3::utils::split(attribute, "\"");
|
|
|
- if (values.size() == 3) {
|
|
|
- add.sql_name = values[1];
|
|
|
- std::size_t pos = values[2].find("false");
|
|
|
- add.no_sql = pos != std::string::npos;
|
|
|
- }
|
|
|
+ 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 (attribute.size() > NoSql.size() && attribute.substr(0, NoSql.size()) == NoSql) {
|
|
|
- attribute = v3::utils::to_upper(attribute);
|
|
|
- if (attribute.find("TRUE") != std::string::npos) {
|
|
|
- add.no_sql = true;
|
|
|
- }
|
|
|
+ }
|
|
|
+ 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 (attribute.size() > Excel.size() && attribute.substr(0, Excel.size()) == Excel) {
|
|
|
- auto values = v3::utils::split(attribute, "\"");
|
|
|
- if (values.size() == 3) {
|
|
|
- add.excel_name = values[1];
|
|
|
- std::size_t pos = values[2].find("false");
|
|
|
- add.no_excel = pos != std::string::npos;
|
|
|
- }
|
|
|
+ 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 (attribute.size() > NoExcel.size() && attribute.substr(0, NoExcel.size()) == NoExcel) {
|
|
|
- attribute = v3::utils::to_upper(attribute);
|
|
|
- if (attribute.find("TRUE") != std::string::npos) {
|
|
|
- add.no_excel = true;
|
|
|
- }
|
|
|
+ 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 if (attribute.size() > NoArchive.size() && attribute.substr(0, NoArchive.size()) == NoArchive) {
|
|
|
- attribute = v3::utils::to_upper(attribute);
|
|
|
- if (attribute.find("TRUE") != std::string::npos) {
|
|
|
- add.no_archive = true;
|
|
|
- }
|
|
|
+ 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;
|
|
|
}
|
|
|
- prop = smatch.suffix();
|
|
|
}
|
|
|
}
|
|
|
- //提取属性
|
|
|
- {
|
|
|
- std::regex pattern("([a-zA-Z_0-9:<>]{1,100})[ \r\n\t]{1,30}([a-zA-Z_0-9]{1,100})");
|
|
|
- std::smatch smatch;
|
|
|
- if (std::regex_search(prop, smatch, pattern)) {
|
|
|
- if (smatch.size() == 3 &&
|
|
|
- ((smatch[1].str().find('<') != std::string::npos && smatch[1].str().find('>') != std::string::npos) ||
|
|
|
- (smatch[1].str().find('<') == std::string::npos && smatch[1].str().find('>') == std::string::npos))) {
|
|
|
- add.type_name = smatch[1];
|
|
|
- add.prop_name = smatch[2];
|
|
|
- add.json_name = add.json_name.empty() ? add.prop_name : add.json_name;
|
|
|
- add.sql_name = add.sql_name.empty() ? add.prop_name : add.sql_name;
|
|
|
- add.excel_name = add.excel_name.empty() ? add.prop_name : add.excel_name;
|
|
|
- result.push_back(add);
|
|
|
+ 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));
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- return result;
|
|
|
- }
|
|
|
- //获取方法
|
|
|
- std::vector<MethodInfo> getMethods(std::string code) {
|
|
|
- std::vector<MethodInfo> result;
|
|
|
- std::vector<std::pair<std::string, std::string>> funcList;
|
|
|
- //提取方法列表
|
|
|
- {
|
|
|
- std::regex pattern("WebResponse[ \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}\\)");
|
|
|
+ /**
|
|
|
+ * @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, pattern)) {
|
|
|
- std::string value = smatch[0];
|
|
|
-
|
|
|
- std::size_t pos = code.find(value);
|
|
|
-
|
|
|
- if (pos == std::string::npos)
|
|
|
- break;
|
|
|
- if (pos > 0)
|
|
|
- pos--;
|
|
|
- std::string func;
|
|
|
- for (int i = pos; i >= 0; --i) {
|
|
|
-
|
|
|
- if (code[i] == ']') {
|
|
|
-
|
|
|
- int count = 0;
|
|
|
-
|
|
|
- for (; i >= 0; --i) {
|
|
|
-
|
|
|
- if (code[i] == '[')
|
|
|
- count++;
|
|
|
-
|
|
|
- func += code[i];
|
|
|
- if (count == 2) {
|
|
|
- i--;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (!(code[i] == '\r' || code[i] == '\n' || code[i] == '\t' || code[i] == ' ')) {
|
|
|
- break;
|
|
|
- }
|
|
|
+ while (std::regex_search(code, smatch, utils::regex::attribute())) {
|
|
|
+ if (smatch.size() == 3) {
|
|
|
+ result.push_back(smatch[0]);
|
|
|
}
|
|
|
- std::reverse(func.begin(), func.end());
|
|
|
- funcList.push_back(std::make_pair(value, func));
|
|
|
code = smatch.suffix();
|
|
|
}
|
|
|
+ return result;
|
|
|
}
|
|
|
-
|
|
|
- for (auto& it : funcList) {
|
|
|
- MethodInfo add;
|
|
|
- //特性
|
|
|
- methodAttribute(it.second, add);
|
|
|
- methodParameter(it.first, add);
|
|
|
- result.push_back(add);
|
|
|
+ };
|
|
|
+
|
|
|
+ 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, ","));
|
|
|
+ }
|
|
|
}
|
|
|
- return result;
|
|
|
- }
|
|
|
- //提取特性
|
|
|
- void methodAttribute(std::string code, MethodInfo& result) {
|
|
|
- auto attributes = v3::utils::split(code, "]]");
|
|
|
-
|
|
|
- for (auto it : attributes) {
|
|
|
-
|
|
|
- std::size_t begin = 0;
|
|
|
- std::size_t end = 0;
|
|
|
-
|
|
|
- //[[ActionType("Page")]]
|
|
|
- if (it.find("[[ActionType") != std::string::npos && (begin = it.find("\"")) != std::string::npos && (end = it.rfind("\"")) != std::string::npos) {
|
|
|
- result.action_type = it.substr(begin + 1, end - begin - 1);
|
|
|
- }
|
|
|
- //[[Method("POST")]]
|
|
|
- if (it.find("[[Method") != std::string::npos && (begin = it.find("\"")) != std::string::npos && (end = it.rfind("\"")) != std::string::npos) {
|
|
|
- std::string value = it.substr(begin + 1, end - begin - 1);
|
|
|
- if (value == "GET") {
|
|
|
- result.method = "robotics::v3::mvc::http_method::GET";
|
|
|
+ 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 {
|
|
|
- result.method = "robotics::v3::mvc::http_method::POST";
|
|
|
+ ss << it.generate_cntlr_code("GET");
|
|
|
}
|
|
|
}
|
|
|
- //[[Authen(false,"Home/Index")]]
|
|
|
- if (it.find("[[Authen") != std::string::npos && (begin = it.find("(")) != std::string::npos && (end = it.find(")")) != std::string::npos && (begin = it.find("\"")) != std::string::npos && (end = it.rfind("\"")) != std::string::npos) {
|
|
|
-
|
|
|
- if (it.find("false") != std::string::npos) {
|
|
|
- result.authen_jump = it.substr(begin + 1, end - begin - 1);
|
|
|
- result.authen = false;
|
|
|
+ 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 {
|
|
|
- result.authen_jump = it.substr(begin + 1, end - begin - 1);
|
|
|
- result.authen = true;
|
|
|
+ ss << "\t\taction->method = robotics::v3::mvc::http_method::GET;" << std::endl;
|
|
|
}
|
|
|
}
|
|
|
- //[[Authen(false)]]
|
|
|
- else if (it.find("[[Authen") != std::string::npos && (begin = it.find("(")) != std::string::npos && (end = it.find(")")) != std::string::npos) {
|
|
|
- std::string value = v3::utils::to_upper(it.substr(begin, end - begin + 1));
|
|
|
- result.authen = value.find("FALSE") == std::string::npos;
|
|
|
+ else {
|
|
|
+ ss << "\t\taction->method = robotics::v3::mvc::http_method::GET;" << std::endl;
|
|
|
}
|
|
|
- //[[Route("Account/Login")]]
|
|
|
- if (it.find("[[Route") != std::string::npos && (begin = it.find("\"")) != std::string::npos && (end = it.rfind("\"")) != std::string::npos) {
|
|
|
- result.route = it.substr(begin + 1, end - begin - 1);
|
|
|
- if (result.route.find('<') != std::string::npos) {
|
|
|
-
|
|
|
- }
|
|
|
+ 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;
|
|
|
}
|
|
|
- //[[ContentType("application/x-www-form-urlencoded")]]
|
|
|
- if (it.find("[[ContentType") != std::string::npos && (begin = it.find("\"")) != std::string::npos && (end = it.rfind("\"")) != std::string::npos) {
|
|
|
- result.content_type = it.substr(begin + 1, end - begin - 1);
|
|
|
+ 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();
|
|
|
}
|
|
|
- //[[FileMapping("Account/Index.html")]]
|
|
|
- if (it.find("[[FileMapping") != std::string::npos && (begin = it.find("\"")) != std::string::npos && (end = it.rfind("\"")) != std::string::npos) {
|
|
|
- result.file_mapping = it.substr(begin + 1, end - begin - 1);
|
|
|
+ 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) + ")";
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
- }
|
|
|
- //
|
|
|
- void methodParameter(std::string code, MethodInfo& result) {
|
|
|
- bool succ = false;
|
|
|
- std::string parameter;
|
|
|
- std::string funcName;
|
|
|
- //提取方法列表
|
|
|
- {
|
|
|
- std::regex pattern("WebResponse[ \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})\\)");
|
|
|
+ /**
|
|
|
+ * @brief 获取特性列表
|
|
|
+ * @param code
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ std::vector<std::string> get_attributes(std::string code) {
|
|
|
+ std::vector<std::string> result;
|
|
|
std::smatch smatch;
|
|
|
- if (std::regex_search(code, smatch, pattern)) {
|
|
|
+ while (std::regex_search(code, smatch, utils::regex::attribute())) {
|
|
|
if (smatch.size() == 3) {
|
|
|
- succ = true;
|
|
|
- funcName = smatch[1];
|
|
|
- parameter = smatch[2];
|
|
|
+ result.push_back(smatch[0]);
|
|
|
}
|
|
|
+ code = smatch.suffix();
|
|
|
}
|
|
|
+ return result;
|
|
|
}
|
|
|
-
|
|
|
- if (!succ)return;
|
|
|
-
|
|
|
- std::vector<ParameterInfo> parameterValues;
|
|
|
- {
|
|
|
- auto parameters = v3::utils::split(parameter, ",");
|
|
|
-
|
|
|
- for (auto& it : parameters) {
|
|
|
- //带特性
|
|
|
- {
|
|
|
- std::regex pattern("\\[\\[(.*?)\\]\\][\r\n\t ]{0,30}([a-zA-Z_0-9<>:]{1,100})[\r\n\t ]{1,30}([a-zA-Z0-9_]{1,100})");
|
|
|
- std::smatch smatch;
|
|
|
- if (std::regex_search(it, smatch, pattern)) {
|
|
|
- if (smatch.size() == 4) {
|
|
|
- ParameterInfo add;
|
|
|
- std::string attribute = smatch[1];
|
|
|
- std::string paramType = smatch[2];
|
|
|
- std::string paramName = smatch[3];
|
|
|
- for (int i = 0; i < paramType.size(); ++i) {
|
|
|
- if (paramType[i] == ' ') {
|
|
|
- paramType.erase(i, 1);
|
|
|
- --i;
|
|
|
- }
|
|
|
- }
|
|
|
- parameterType(paramType, add);
|
|
|
- parameterAttribute(attribute, add);
|
|
|
- if (add.parameter_name.empty()) {
|
|
|
- add.parameter_name = paramName;
|
|
|
+ /**
|
|
|
+ * @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 (add.parameter_name == " ") {
|
|
|
- add.parameter_name = "";
|
|
|
+ if (item.size() > 1) {
|
|
|
+ ss << utils::string::join(item, ".\n\t\t") << ";" << std::endl;
|
|
|
}
|
|
|
- add.name = paramName;
|
|
|
- add.type = paramType;
|
|
|
- parameterValues.push_back(add);
|
|
|
- continue;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- //不带特性
|
|
|
- {
|
|
|
- std::regex pattern("([a-zA-Z_0-9<>:]{1,100})[\r\n\t ]{1,30}([a-zA-Z0-9_]{1,100})");
|
|
|
- std::smatch smatch;
|
|
|
- if (std::regex_search(it, smatch, pattern)) {
|
|
|
- if (smatch.size() == 3) {
|
|
|
- ParameterInfo add;
|
|
|
- std::string paramType = smatch[1];
|
|
|
- std::string paramName = smatch[2];
|
|
|
- for (int i = 0; i < paramType.size(); ++i) {
|
|
|
- if (paramType[i] == ' ') {
|
|
|
- paramType.erase(i, 1);
|
|
|
- --i;
|
|
|
- }
|
|
|
- }
|
|
|
- parameterType(paramType, add);
|
|
|
- add.name = paramName;
|
|
|
- add.type = paramType;
|
|
|
- add.parameter_name = paramName;
|
|
|
- parameterValues.push_back(add);
|
|
|
- continue;
|
|
|
- }
|
|
|
+
|
|
|
+ }
|
|
|
+ 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;
|
|
|
}
|
|
|
- }
|
|
|
- result.parameters = parameterValues;
|
|
|
-
|
|
|
- std::string signature = "WebResponse({})";
|
|
|
-
|
|
|
- std::vector<std::string> tmpParams;
|
|
|
-
|
|
|
- for (auto& it : result.parameters) {
|
|
|
- tmpParams.push_back(it.type);
|
|
|
- }
|
|
|
-
|
|
|
- signature = v3::utils::format(signature, v3::utils::join(tmpParams, ","));
|
|
|
-
|
|
|
- result.signature = signature;
|
|
|
-
|
|
|
- result.name = funcName;
|
|
|
- }
|
|
|
- void parameterType(std::string code, ParameterInfo& parameter) {
|
|
|
- if (code == "robotics::v3::mvc::multipart_value" || code == "v3::mvc::multipart_value" || code == "mvc::multipart_value" || code == "multipart_value") {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::Multipart";
|
|
|
- }
|
|
|
- else if (code == "int") {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::Int";
|
|
|
- }
|
|
|
- else if (code == "std::uint64_t") {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::Int64";
|
|
|
- }
|
|
|
- else if (code == "float") {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::Float";
|
|
|
- }
|
|
|
- else if (code == "double") {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::Double";
|
|
|
- }
|
|
|
- else if (code == "long") {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::Long";
|
|
|
- }
|
|
|
- else if (code == "bool") {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::Bool_";
|
|
|
- }
|
|
|
- else if (code == "std::string") {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::String";
|
|
|
- }
|
|
|
- else if (code == "robotics::v3::datetime" || code == "v3::datetime" || code == "datetime") {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::DateTime";
|
|
|
- }
|
|
|
- else if (code == "std::vector<std::uint8_t>") {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::Binary";
|
|
|
- }
|
|
|
- else if (code == "std::vector<int>") {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::VecInt";
|
|
|
- }
|
|
|
- else if (code == "std::vector<std::uint64_t>") {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::VecInt64";
|
|
|
- }
|
|
|
- else if (code == "std::vector<float>") {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::VecFloat";
|
|
|
- }
|
|
|
- else if (code == "std::vector<double>") {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::VecDouble";
|
|
|
- }
|
|
|
- else if (code == "std::vector<long>") {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::VecLong";
|
|
|
- }
|
|
|
- else if (code == "std::vector<bool>") {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::VecBool";
|
|
|
- }
|
|
|
- else if (code == "std::vector<std::string>") {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::VecString";
|
|
|
- }
|
|
|
- else if (code == "std::vector<robotics::v3::datetime>" || code == "std::vector<v3::datetime>" || code == "std::vector<datetime>") {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::VecDateTime";
|
|
|
- }
|
|
|
- else if (code.size() > 12 && code.substr(0, 11) == "std::vector") {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::VecJson";
|
|
|
- }
|
|
|
- else {
|
|
|
- parameter.argument_type = "robotics::v3::mvc::argument_type::Json";
|
|
|
- }
|
|
|
- }
|
|
|
- void parameterAttribute(std::string code, ParameterInfo& parameter) {
|
|
|
-
|
|
|
- std::size_t begin = 0;
|
|
|
- std::size_t end = 0;
|
|
|
-
|
|
|
- //FromQuery
|
|
|
- if (code.find("FromQuery") != std::string::npos && (begin = code.find("\"")) != std::string::npos && (end = code.rfind("\"")) != std::string::npos) {
|
|
|
- parameter.from_storage_type = "robotics::v3::mvc::from_storage_type::QUERY";
|
|
|
- parameter.parameter_name = code.substr(begin + 1, end - begin - 1);
|
|
|
- }
|
|
|
- //FromBody
|
|
|
- else if (code.find("FromBody") != std::string::npos && (begin = code.find("\"")) != std::string::npos && (end = code.rfind("\"")) != std::string::npos) {
|
|
|
- parameter.from_storage_type = "robotics::v3::mvc::from_storage_type::BODY";
|
|
|
- parameter.parameter_name = code.substr(begin + 1, end - begin - 1);
|
|
|
- if (parameter.parameter_name.empty()) {
|
|
|
- parameter.parameter_name = " ";
|
|
|
+ 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;
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- //FromHeader
|
|
|
- else if (code.find("FromHeader") != std::string::npos && (begin = code.find("\"")) != std::string::npos && (end = code.rfind("\"")) != std::string::npos) {
|
|
|
- parameter.from_storage_type = "robotics::v3::mvc::from_storage_type::HEADER";
|
|
|
- parameter.parameter_name = code.substr(begin + 1, end - begin - 1);
|
|
|
- }
|
|
|
- //FromUrl
|
|
|
- else if (code.find("FromUrl") != std::string::npos && (begin = code.find("\"")) != std::string::npos && (end = code.rfind("\"")) != std::string::npos) {
|
|
|
- parameter.from_storage_type = "robotics::v3::mvc::from_storage_type::URL";
|
|
|
- parameter.parameter_name = code.substr(begin + 1, end - begin - 1);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- void getSoapAttribute(std::string code, class_view_info& result) {
|
|
|
- std::size_t begin = 0;
|
|
|
- std::size_t end = 0;
|
|
|
-
|
|
|
- //Version
|
|
|
- if (code.find("Version") != std::string::npos && (begin = code.find("\"")) != std::string::npos && (end = code.rfind("\"")) != std::string::npos) {
|
|
|
- result.soap_version = code.substr(begin + 1, end - begin - 1);
|
|
|
- }
|
|
|
- //Namepsace
|
|
|
- else if (code.find("Namespace") != std::string::npos && (begin = code.find("\"")) != std::string::npos && (end = code.rfind("\"")) != std::string::npos) {
|
|
|
- result.soap_namepsace = code.substr(begin + 1, end - begin - 1);
|
|
|
- }
|
|
|
- //Route
|
|
|
- else if (code.find("Route") != std::string::npos && (begin = code.find("\"")) != std::string::npos && (end = code.rfind("\"")) != std::string::npos) {
|
|
|
- result.soap_route = code.substr(begin + 1, end - begin - 1);
|
|
|
- }
|
|
|
- //Wsdl
|
|
|
- else if (code.find("Wsdl") != std::string::npos && (begin = code.find("\"")) != std::string::npos && (end = code.rfind("\"")) != std::string::npos) {
|
|
|
- result.soap_wsdl = code.substr(begin + 1, end - begin - 1);
|
|
|
- }
|
|
|
- }
|
|
|
- std::vector<soap_method_info> getSoapMethods(std::string code) {
|
|
|
- std::vector<soap_method_info> result;
|
|
|
- std::vector<std::pair<std::string, std::string>> funcList;
|
|
|
- //提取方法列表
|
|
|
- {
|
|
|
- std::regex pattern("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}\\)");
|
|
|
+ ss << "}" << std::endl;
|
|
|
+ return std::pair(funcname, ss.str());
|
|
|
+ }
|
|
|
+ private:
|
|
|
+ /**
|
|
|
+ * @brief
|
|
|
+ * @param code
|
|
|
+ */
|
|
|
+ void deserialize(std::string code) {
|
|
|
std::smatch smatch;
|
|
|
- while (std::regex_search(code, smatch, pattern)) {
|
|
|
- std::string value = smatch[0];
|
|
|
-
|
|
|
- std::size_t pos = code.find(value);
|
|
|
-
|
|
|
- if (pos == std::string::npos)
|
|
|
- break;
|
|
|
- if (pos > 0)
|
|
|
- pos--;
|
|
|
- std::string func;
|
|
|
- for (int i = pos; i >= 0; --i) {
|
|
|
-
|
|
|
- if (code[i] == ']') {
|
|
|
-
|
|
|
- int count = 0;
|
|
|
-
|
|
|
- for (; i >= 0; --i) {
|
|
|
-
|
|
|
- if (code[i] == '[')
|
|
|
- count++;
|
|
|
-
|
|
|
- func += code[i];
|
|
|
- if (count == 2) {
|
|
|
- i--;
|
|
|
- break;
|
|
|
+ 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);
|
|
|
}
|
|
|
-
|
|
|
- if (!(code[i] == '\r' || code[i] == '\n' || code[i] == '\t' || code[i] == ' ')) {
|
|
|
- break;
|
|
|
+ else {
|
|
|
+ code = smatch.suffix();
|
|
|
}
|
|
|
}
|
|
|
- std::reverse(func.begin(), func.end());
|
|
|
- funcList.push_back(std::make_pair(value, func));
|
|
|
+ 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;
|
|
|
}
|
|
|
-
|
|
|
- for (auto& it : funcList) {
|
|
|
- soap_method_info add;
|
|
|
- //特性
|
|
|
- soapMethodAttribute(it.second, add);
|
|
|
- soapMethodParameter(it.first, add);
|
|
|
- result.push_back(add);
|
|
|
+ /**
|
|
|
+ * @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;
|
|
|
}
|
|
|
- return result;
|
|
|
- }
|
|
|
- void soapMethodAttribute(std::string code, soap_method_info& result) {
|
|
|
- auto attributes = v3::utils::split(code, "]]");
|
|
|
-
|
|
|
- for (auto it : attributes) {
|
|
|
-
|
|
|
- std::size_t begin = 0;
|
|
|
- std::size_t end = 0;
|
|
|
-
|
|
|
- //[[Method("get")]]
|
|
|
- if (it.find("Method") != std::string::npos && (begin = it.find("\"")) != std::string::npos && (end = it.rfind("\"")) != std::string::npos) {
|
|
|
- result.action_name = it.substr(begin + 1, end - begin - 1);
|
|
|
+ /**
|
|
|
+ * @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;
|
|
|
}
|
|
|
- }
|
|
|
- void soapMethodParameter(std::string code, soap_method_info& result) {
|
|
|
- std::regex pattern("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})\\)");
|
|
|
- std::smatch smatch;
|
|
|
- std::vector<SoapParameterInfo> parameterValues;
|
|
|
- while (std::regex_search(code, smatch, pattern)) {
|
|
|
- if (smatch.size() == 3) {
|
|
|
- result.name = smatch[1];
|
|
|
- if (result.action_name.empty()) {
|
|
|
- result.action_name = result.name;
|
|
|
+ /**
|
|
|
+ * @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]);
|
|
|
}
|
|
|
-
|
|
|
- auto parameters = v3::utils::split(smatch[2], ",");
|
|
|
-
|
|
|
-
|
|
|
- for (auto& it : parameters)
|
|
|
- {
|
|
|
- std::regex pattern1("([a-zA-Z_0-9<>:]{1,100})[\r\n\t ]{1,30}([a-zA-Z0-9_]{1,100})");
|
|
|
- std::smatch smatch1;
|
|
|
- if (std::regex_search(it, smatch1, pattern1)) {
|
|
|
- if (smatch1.size() == 3) {
|
|
|
- SoapParameterInfo add;
|
|
|
- std::string paramType = smatch1[1];
|
|
|
- std::string paramName = smatch1[2];
|
|
|
- for (int i = 0; i < paramType.size(); ++i) {
|
|
|
- if (paramType[i] == ' ') {
|
|
|
- paramType.erase(i, 1);
|
|
|
- --i;
|
|
|
- }
|
|
|
- }
|
|
|
- soapParameterType(paramType, add);
|
|
|
- add.parameter_name = paramName;
|
|
|
- add.type = paramType;
|
|
|
- parameterValues.push_back(add);
|
|
|
- continue;
|
|
|
- }
|
|
|
+ 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();
|
|
|
+ }
|
|
|
}
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- result.parameters = parameterValues;
|
|
|
-
|
|
|
- std::string signature = "SoapResponse({})";
|
|
|
-
|
|
|
- std::vector<std::string> tmpParams;
|
|
|
-
|
|
|
- for (auto& it : result.parameters) {
|
|
|
- tmpParams.push_back(it.type);
|
|
|
- }
|
|
|
-
|
|
|
- signature = v3::utils::format(signature, v3::utils::join(tmpParams, ","));
|
|
|
-
|
|
|
- result.signature = signature;
|
|
|
- }
|
|
|
- void soapParameterType(std::string code, SoapParameterInfo& parameter) {
|
|
|
-
|
|
|
- if (code == "int") {
|
|
|
- parameter.argument_type = "robotics::v3::soap::soap_argument_type::Int";
|
|
|
}
|
|
|
- else if (code == "std::uint64_t") {
|
|
|
- parameter.argument_type = "robotics::v3::soap::soap_argument_type::Int64";
|
|
|
+ /**
|
|
|
+ * @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());
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- else if (code == "float") {
|
|
|
- parameter.argument_type = "robotics::v3::soap::soap_argument_type::Float";
|
|
|
+ };
|
|
|
+
|
|
|
+ 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_ += '/';
|
|
|
+ }
|
|
|
}
|
|
|
- else if (code == "double") {
|
|
|
- parameter.argument_type = "robotics::v3::soap::soap_argument_type::Double";
|
|
|
+ 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;
|
|
|
}
|
|
|
- else if (code == "long") {
|
|
|
- parameter.argument_type = "robotics::v3::soap::soap_argument_type::Long";
|
|
|
+ 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;
|
|
|
}
|
|
|
- else if (code == "bool") {
|
|
|
- parameter.argument_type = "robotics::v3::soap::soap_argument_type::Bool_";
|
|
|
+ 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;
|
|
|
}
|
|
|
- else if (code == "std::string") {
|
|
|
- parameter.argument_type = "robotics::v3::soap::soap_argument_type::String";
|
|
|
+ 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;
|
|
|
}
|
|
|
- else if (code == "robotics::v3::datetime" || code == "v3::datetime" || code == "datetime") {
|
|
|
- parameter.argument_type = "robotics::v3::soap::soap_argument_type::DateTime";
|
|
|
+ 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 "";
|
|
|
}
|
|
|
- else {
|
|
|
- parameter.argument_type = "robotics::v3::soap_argument_type::Json";
|
|
|
+ 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::filesystem::path _path;
|
|
|
-};
|
|
|
-
|
|
|
-#endif //!__CODE_GENERATOR_CODE_ANALYSIS_H__
|
|
|
+ private:
|
|
|
+ std::string path_;
|
|
|
+ };
|
|
|
+}
|