XNSim/XNModelGenServer/XNModelGen.cpp

693 lines
25 KiB
C++
Raw Normal View History

#include "XNModelGen.h"
#include <sqlite3.h>
#include <stdexcept>
#include <filesystem>
#include <cstdlib>
#include <fstream>
#include <algorithm>
#include <nlohmann/json.hpp>
#include <sstream>
using json = nlohmann::json;
namespace fs = std::filesystem;
XNModelGen::XNModelGen()
{
}
XNModelGen::~XNModelGen()
{
}
const std::string &XNModelGen::GetCodePath() const
{
return m_codePath;
}
int XNModelGen::Initialize(const std::string &className, const std::string &version,
const std::string &planeName, std::string &errorMsg)
{
std::string dbPath = GetXNCorePath() + "/database/XNSim.db";
sqlite3 *db;
int rc = sqlite3_open(dbPath.c_str(), &db);
if (rc != SQLITE_OK) {
errorMsg = "无法打开数据库: " + std::string(sqlite3_errmsg(db));
return -1;
}
std::string sql =
"SELECT * FROM XNModelsVersion WHERE ClassName = ? AND Version = ? AND PlaneName = ?";
sqlite3_stmt *stmt;
rc = sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr);
if (rc != SQLITE_OK) {
errorMsg = "准备XNModelsVersion表SQL语句失败: " + std::string(sqlite3_errmsg(db));
sqlite3_close(db);
return -1;
}
// 绑定参数
sqlite3_bind_text(stmt, 1, className.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 2, version.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 3, planeName.c_str(), -1, SQLITE_STATIC);
// 执行查询
rc = sqlite3_step(stmt);
if (rc == SQLITE_ROW) {
// 读取数据到成员变量 - 按照CREATE TABLE语句的字段顺序
m_planeName = (const char *)sqlite3_column_text(stmt, 0); // PlaneName
m_className = (const char *)sqlite3_column_text(stmt, 1); // ClassName
m_version = (const char *)sqlite3_column_text(stmt, 2); // Version
m_confID = sqlite3_column_int(stmt, 3); // ConfID (INTEGER)
m_name = (const char *)sqlite3_column_text(stmt, 4); // Name
m_author = (const char *)sqlite3_column_text(stmt, 5); // Author
m_description = (const char *)sqlite3_column_text(stmt, 6); // Description
m_createTime = (const char *)sqlite3_column_text(stmt, 7); // CreatTime
m_changeTime = (const char *)sqlite3_column_text(stmt, 8); // ChangeTime
m_runFreq = std::to_string(sqlite3_column_int(stmt, 9)); // RunFreqGroup (INTEGER)
m_runNode = std::to_string(sqlite3_column_int(stmt, 10)); // RunNode (INTEGER)
m_priority = std::to_string(sqlite3_column_int(stmt, 11)); // Priority (INTEGER)
m_dataPackagePath = (const char *)sqlite3_column_text(stmt, 12); // DataPackagePath
m_dataPackageName = (const char *)sqlite3_column_text(stmt, 13); // DataPackageName
m_dataPackageHeaderName =
(const char *)sqlite3_column_text(stmt, 14); // DataPackageHeaderName
m_dataPackageEntryPoint =
(const char *)sqlite3_column_text(stmt, 15); // DataPackageEntryPoint
m_dataPackageInterfaceName =
(const char *)sqlite3_column_text(stmt, 16); // DataPackageInterfaceName
std::string inputStruct = (const char *)sqlite3_column_text(stmt, 17); // InputStruct
ParseStructName(inputStruct, m_inputStructName_Interface, m_inputStructName.originalName);
ParseStructOriginalName(m_inputStructName);
std::string outputStruct = (const char *)sqlite3_column_text(stmt, 18); // OutputStruct
ParseStructName(outputStruct, m_outputStructName_Interface,
m_outputStructName.originalName);
ParseStructOriginalName(m_outputStructName);
std::string heartStruct = (const char *)sqlite3_column_text(stmt, 19); // HeartStruct
ParseStructName(heartStruct, m_heartStructName_Interface, m_heartStructName.originalName);
ParseStructOriginalName(m_heartStructName);
// TODO cmdList暂不读取
} else if (rc == SQLITE_DONE) {
// 没有找到数据
errorMsg = "未找到匹配的XNModelsVersion记录";
sqlite3_finalize(stmt);
sqlite3_close(db);
return -2;
} else {
// 查询出错
errorMsg = "查询XNModelsVersion表执行失败: " + std::string(sqlite3_errmsg(db));
sqlite3_finalize(stmt);
sqlite3_close(db);
return -3;
}
sqlite3_finalize(stmt);
// 根据m_confID查询Configuration表
if (m_confID > 0) {
std::string confSql = "SELECT ConfName FROM Configuration WHERE ConfID = ?";
sqlite3_stmt *confStmt;
rc = sqlite3_prepare_v2(db, confSql.c_str(), -1, &confStmt, nullptr);
if (rc != SQLITE_OK) {
errorMsg = "准备Configuration表SQL语句失败: " + std::string(sqlite3_errmsg(db));
sqlite3_close(db);
return -4;
}
// 绑定参数 - ConfID是INTEGER类型
sqlite3_bind_int(confStmt, 1, m_confID);
// 执行查询
rc = sqlite3_step(confStmt);
if (rc == SQLITE_ROW) {
// 读取Configuration表数据
m_confName = (const char *)sqlite3_column_text(confStmt, 0); // ConfName
} else if (rc == SQLITE_DONE) {
// 没有找到Configuration记录
errorMsg = "未找到匹配的Configuration记录,ConfID: " + std::to_string(m_confID);
sqlite3_finalize(confStmt);
sqlite3_close(db);
return -5;
} else {
// Configuration查询出错
errorMsg = "查询Configuration表执行失败: " + std::string(sqlite3_errmsg(db));
sqlite3_finalize(confStmt);
sqlite3_close(db);
return -6;
}
sqlite3_finalize(confStmt);
}
sqlite3_close(db);
//目录组装
if (m_confName.empty()) {
errorMsg = "Configuration表ConfName为空";
return -7;
}
m_workPath = GetXNCorePath() + "/Configuration/" + m_confName;
m_modelsPath = m_workPath + "/Models";
m_codePath = m_workPath + "/ModelProjects/" + className + "_" + version;
m_hasDataPackage = false;
if (!m_dataPackagePath.empty() && !m_dataPackageHeaderName.empty()
&& !m_dataPackageInterfaceName.empty() && !m_dataPackageEntryPoint.empty()) {
m_hasDataPackage = true;
}
return 0;
}
int XNModelGen::GenerateCode(std::string &errorMsg)
{
// 检查代码目录是否存在,不存在则创建
if (!fs::exists(m_codePath)) {
try {
fs::create_directories(m_codePath);
} catch (const fs::filesystem_error &e) {
errorMsg = "创建代码目录失败: " + std::string(e.what());
return -1;
}
}
bool ret = GenerateHeaderFile();
if (!ret) {
errorMsg = "生成头文件失败";
return -2;
}
ret = GenerateSourceFile();
if (!ret) {
errorMsg = "生成源文件失败";
return -3;
}
ret = GenerateConfigFile();
if (!ret) {
errorMsg = "生成配置文件失败";
return -4;
}
ret = GenerateCMakeLists();
if (!ret) {
errorMsg = "生成CMakeLists.txt失败";
return -5;
}
return 0;
}
bool XNModelGen::GenerateHeaderFile()
{
std::string globalHeaderPath = m_codePath + "/" + m_className + "_global.h";
std::ofstream globalHeaderFile(globalHeaderPath);
if (!globalHeaderFile.is_open()) {
return false;
}
std::string upperClassName = UpperCase(m_className);
// 导入导出定义文件
globalHeaderFile << "#ifndef " << upperClassName << "_GLOBAL_H" << std::endl;
globalHeaderFile << "#define " << upperClassName << "_GLOBAL_H" << std::endl;
globalHeaderFile << std::endl;
globalHeaderFile << "#if defined(" << upperClassName << "_LIBRARY)" << std::endl;
globalHeaderFile << "#define " << upperClassName
<< "_EXPORT __attribute__((visibility(\"default\")))" << std::endl;
globalHeaderFile << "#else" << std::endl;
globalHeaderFile << "#define " << upperClassName
<< "_EXPORT __attribute__((visibility(\"default\")))" << std::endl;
globalHeaderFile << "#endif" << std::endl;
globalHeaderFile << std::endl;
globalHeaderFile << "#endif // " << upperClassName << "_GLOBAL_H" << std::endl;
globalHeaderFile << std::endl;
globalHeaderFile.close();
// 模型头文件
std::string headerPath = m_codePath + "/" + m_className + ".h";
std::ofstream headerFile(headerPath);
if (!headerFile.is_open()) {
return false;
}
headerFile << "#pragma once" << std::endl;
headerFile << std::endl;
headerFile << "#include \"" << m_className << "_global.h\"" << std::endl;
headerFile << "#include <XNCore/XNModelObject.h>" << std::endl;
headerFile << std::endl;
headerFile << "struct " << m_className << "Private;" << std::endl;
headerFile << std::endl;
headerFile << "class " << upperClassName << "_EXPORT " << m_className
<< " : public XNModelObject" << std::endl;
headerFile << "{" << std::endl;
headerFile << "XN_METATYPE(" << m_className << ", XNModelObject)" << std::endl;
headerFile << "XN_DECLARE_PRIVATE(" << m_className << ")" << std::endl;
headerFile << "public:" << std::endl;
headerFile << " " << m_className << "();" << std::endl;
headerFile << " virtual ~" << m_className << "();" << std::endl;
headerFile << std::endl;
headerFile << "protected:" << std::endl;
headerFile << " " << m_className << "(PrivateType *p);" << std::endl;
headerFile << std::endl;
headerFile << "public:" << std::endl;
headerFile << " virtual void Initialize() override;" << std::endl;
headerFile << " virtual void PrepareForExecute() override;" << std::endl;
headerFile << " virtual void StepUpdate() override;" << std::endl;
headerFile << std::endl;
headerFile << "protected:" << std::endl;
headerFile << " void InitializeData();" << std::endl;
headerFile << " void ReleaseData();" << std::endl;
headerFile << "};" << std::endl;
headerFile << std::endl;
headerFile << "XNCLASS_PTR_DECLARE(" << m_className << ")" << std::endl;
headerFile << std::endl;
headerFile.close();
// 私有结构体头文件
std::string pHeaderPath = m_codePath + "/" + m_className + "_p.h";
std::ofstream pHeaderFile(pHeaderPath);
if (!pHeaderFile.is_open()) {
return false;
}
pHeaderFile << "#pragma once" << std::endl;
pHeaderFile << std::endl;
pHeaderFile << "#include <XNCore/XNModelObject_p.h>" << std::endl;
if (m_hasDataPackage) {
pHeaderFile << "#include \"../../Packages/" << m_dataPackagePath << "/"
<< m_dataPackageHeaderName << "\"" << std::endl;
}
pHeaderFile << "#include \"../../IDL/" << m_confName << "_Interface.h\"" << std::endl;
pHeaderFile << std::endl;
if (m_hasDataPackage) {
pHeaderFile << "using InterfaceType = " << m_dataPackageInterfaceName << ";" << std::endl;
pHeaderFile << "typedef void (*FunctionType)(InterfaceType *);" << std::endl;
pHeaderFile << std::endl;
}
pHeaderFile << "struct " << m_className << "Private : public XNModelObjectPrivate{"
<< std::endl;
if (m_hasDataPackage) {
pHeaderFile << " FunctionType _fun = nullptr;" << std::endl;
pHeaderFile << " InterfaceType _data;" << std::endl;
pHeaderFile << " std::string _entryPointName = \"" << m_dataPackageEntryPoint << "\";"
<< std::endl;
}
pHeaderFile << " std::mutex _mutex;" << std::endl;
if (!m_inputStructName_Interface.empty()) {
pHeaderFile << " " << m_inputStructName_Interface << "_Interface _inputInterface;"
<< std::endl;
}
if (!m_outputStructName_Interface.empty()) {
pHeaderFile << " " << m_outputStructName_Interface << "_Interface _outputInterface;"
<< std::endl;
}
if (!m_heartStructName_Interface.empty()) {
pHeaderFile << " " << m_heartStructName_Interface << "_Interface _heartbeatInterface;"
<< std::endl;
}
pHeaderFile << "};" << std::endl;
pHeaderFile << std::endl;
pHeaderFile.close();
return true;
}
bool XNModelGen::GenerateSourceFile()
{
// 源文件
std::string sourcePath = m_codePath + "/" + m_className + ".cpp";
std::ofstream sourceFile(sourcePath);
if (!sourceFile.is_open()) {
return false;
}
sourceFile << "#include \"" << m_className << ".h\"" << std::endl;
sourceFile << "#include \"" << m_className << "_p.h\"" << std::endl;
sourceFile << "#include <XNCore/XNModelManager.h>" << std::endl;
sourceFile << std::endl;
sourceFile << "XN_MODEL_INITIALIZE(" << m_className << ")" << std::endl;
sourceFile << std::endl;
sourceFile << m_className << "::" << m_className << "() : XNModelObject("
<< "new " << m_className << "Private())" << std::endl;
sourceFile << "{" << std::endl;
sourceFile << "}" << std::endl;
sourceFile << std::endl;
sourceFile << m_className << "::~" << m_className << "() {" << std::endl;
sourceFile << "}" << std::endl;
sourceFile << std::endl;
sourceFile << m_className << "::" << m_className << "(PrivateType *p) : XNModelObject(p)"
<< std::endl;
sourceFile << "{" << std::endl;
sourceFile << "}" << std::endl;
sourceFile << std::endl;
sourceFile << "void " << m_className << "::Initialize() {" << std::endl;
sourceFile << " T_D();" << std::endl;
sourceFile << " SuperType::Initialize();" << std::endl;
if (m_hasDataPackage) {
sourceFile << " if (d->_dynamicLib) {" << std::endl;
sourceFile
<< " d->_fun = (FunctionType)dlsym(d->_dynamicLib, d->_entryPointName.c_str());"
<< std::endl;
sourceFile << " if (!d->_fun) {" << std::endl;
sourceFile << " LOG_WARNING(\"Failed to resolve " << m_dataPackageEntryPoint
<< "\");" << std::endl;
sourceFile << " }" << std::endl;
sourceFile << " }" << std::endl;
}
sourceFile << " /* 在这里进行其它初始化 */" << std::endl;
sourceFile << "}" << std::endl;
sourceFile << std::endl;
sourceFile << "void " << m_className << "::PrepareForExecute() {" << std::endl;
sourceFile << " T_D();" << std::endl;
sourceFile << " SuperType::PrepareForExecute();" << std::endl;
sourceFile << " InitializeData();" << std::endl;
if (!m_inputStructName_Interface.empty()) {
sourceFile << " d->_inputInterface.Initialize(GetFramework(), GetUniqueId(), 1);"
<< std::endl;
}
if (!m_outputStructName_Interface.empty()) {
sourceFile << " d->_outputInterface.Initialize(GetFramework(), GetUniqueId(), 2);"
<< std::endl;
}
if (!m_heartStructName_Interface.empty()) {
sourceFile << " d->_heartbeatInterface.Initialize(GetFramework(), GetUniqueId(), 2);"
<< std::endl;
}
sourceFile << " /* 在这里进行其它运行前准备工作 */" << std::endl;
sourceFile << "}" << std::endl;
sourceFile << std::endl;
sourceFile << "void " << m_className << "::StepUpdate() {" << std::endl;
sourceFile << " T_D();" << std::endl;
sourceFile << " SuperType::StepUpdate();" << std::endl;
if (m_hasDataPackage) {
sourceFile << " if(d->_fun){" << std::endl;
if (!m_inputStructName_Interface.empty() && !m_inputStructName.structName.empty()) {
if (m_inputStructName.isPointer) {
sourceFile << " d->_inputInterface.getData(d->_data."
<< m_inputStructName.structName << ");" << std::endl;
} else {
sourceFile << " d->_inputInterface.getData(&d->_data."
<< m_inputStructName.structName << ");" << std::endl;
}
}
sourceFile << " d->_fun(&d->_data);" << std::endl;
if (!m_outputStructName_Interface.empty() && !m_outputStructName.structName.empty()) {
if (m_outputStructName.isPointer) {
sourceFile << " d->_outputInterface.setData(d->_data."
<< m_outputStructName.structName << ");" << std::endl;
} else {
sourceFile << " d->_outputInterface.setData(&d->_data."
<< m_outputStructName.structName << ");" << std::endl;
}
}
// 这里只适用于本体模型
if (!m_heartStructName_Interface.empty() && !m_heartStructName.structName.empty()) {
if (m_heartStructName.isNumeric) {
sourceFile << " d->_heartbeatInterface.setData(&d->_data);" << std::endl;
}
}
sourceFile << " }" << std::endl;
}
sourceFile << " /* 在这里进行其它运行时计算 */" << std::endl;
sourceFile << "}" << std::endl;
sourceFile << std::endl;
sourceFile << "void " << m_className << "::InitializeData() {" << std::endl;
sourceFile << " T_D();" << std::endl;
if (!m_inputStructName.structName.empty()) {
if (m_inputStructName.isPointer) {
sourceFile << " d->_data." << m_inputStructName.structName << " = new "
<< m_inputStructName.structType << ";" << std::endl;
}
sourceFile << " // TODO: 在这里初始化输入数据" << std::endl;
sourceFile << std::endl;
}
if (!m_outputStructName.structName.empty()) {
if (m_outputStructName.isPointer) {
sourceFile << " d->_data." << m_outputStructName.structName << " = new "
<< m_outputStructName.structType << ";" << std::endl;
}
sourceFile << " // TODO: 在这里初始化输出数据" << std::endl;
sourceFile << std::endl;
}
// 心跳数据,仅适用于本体模型
if (!m_heartStructName.structName.empty()) {
if (m_heartStructName.isNumeric) {
sourceFile << " d->_data." << m_heartStructName.structName << " = 0;" << std::endl;
}
}
sourceFile << "}" << std::endl;
sourceFile << std::endl;
sourceFile << "void " << m_className << "::ReleaseData() {" << std::endl;
sourceFile << " T_D();" << std::endl;
if (!m_inputStructName.structName.empty()) {
sourceFile << " // TODO: 在这里释放输入数据" << std::endl;
sourceFile << std::endl;
if (m_inputStructName.isPointer) {
sourceFile << " if (d->_data." << m_inputStructName.structName << ") {" << std::endl;
sourceFile << " delete d->_data." << m_inputStructName.structName << ";"
<< std::endl;
sourceFile << " d->_data." << m_inputStructName.structName << " = nullptr;"
<< std::endl;
sourceFile << " }" << std::endl;
}
}
if (!m_outputStructName.structName.empty()) {
sourceFile << " // TODO: 在这里释放输出数据" << std::endl;
sourceFile << std::endl;
if (m_outputStructName.isPointer) {
sourceFile << " if (d->_data." << m_outputStructName.structName << ") {"
<< std::endl;
sourceFile << " delete d->_data." << m_outputStructName.structName << ";"
<< std::endl;
sourceFile << " d->_data." << m_outputStructName.structName << " = nullptr;"
<< std::endl;
sourceFile << " }" << std::endl;
}
}
sourceFile << "}" << std::endl;
sourceFile << std::endl;
return true;
}
bool XNModelGen::GenerateConfigFile()
{
std::string configPath = m_codePath + "/" + m_className + ".mcfg";
std::ofstream configFile(configPath);
if (!configFile.is_open()) {
return false;
}
configFile << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
configFile << "<Model>" << std::endl;
configFile << " <Name>" << m_className << "</Name>" << std::endl;
configFile << " <Description>" << m_description << "</Description>" << std::endl;
configFile << " <Author>" << m_author << "</Author>" << std::endl;
configFile << " <Version>" << m_version << "</Version>" << std::endl;
configFile << " <CreateTime>" << m_createTime << "</CreateTime>" << std::endl;
configFile << " <ChangeTime>" << m_changeTime << "</ChangeTime>" << std::endl;
configFile << " <Node>" << m_runNode << "</Node>" << std::endl;
configFile << " <Priority>" << m_priority << "</Priority>" << std::endl;
configFile << " <MathLib>" << m_dataPackagePath << "/" << m_dataPackageName << "</MathLib>"
<< std::endl;
// TODO: 添加命令列表
configFile << " <CommandList/>" << std::endl;
configFile << "</Model>" << std::endl;
configFile.close();
return true;
}
bool XNModelGen::GenerateCMakeLists()
{
std::string cmakeListsPath = m_codePath + "/CMakeLists.txt";
std::ofstream cmakeListsFile(cmakeListsPath);
if (!cmakeListsFile.is_open()) {
return false;
}
cmakeListsFile << "cmake_minimum_required(VERSION 3.16)" << std::endl;
cmakeListsFile << std::endl;
cmakeListsFile << "project(" << m_className << " LANGUAGES CXX)" << std::endl;
cmakeListsFile << std::endl;
cmakeListsFile << "set(MODEL_VERSION \"" << m_version << "\")" << std::endl;
cmakeListsFile << std::endl;
cmakeListsFile << "set(CMAKE_CXX_STANDARD 17)" << std::endl;
cmakeListsFile << "set(CMAKE_CXX_STANDARD_REQUIRED ON)" << std::endl;
cmakeListsFile << "set(CMAKE_POSITION_INDEPENDENT_CODE ON)" << std::endl;
cmakeListsFile << std::endl;
// 获取环境变量
cmakeListsFile << "if(DEFINED ENV{XNCore})" << std::endl;
cmakeListsFile << " set(XNCore_PATH $ENV{XNCore})" << std::endl;
cmakeListsFile << "else()" << std::endl;
cmakeListsFile << " message(FATAL_ERROR \"Environment variable XNCore is not set.\")"
<< std::endl;
cmakeListsFile << "endif()" << std::endl;
cmakeListsFile << std::endl;
// 添加 XNCore_PATH 下的 include 目录为包含目录
cmakeListsFile << "include_directories(${XNCore_PATH}/include)" << std::endl;
cmakeListsFile << "include_directories(${XNCore_PATH}/IDL)" << std::endl;
cmakeListsFile << std::endl;
cmakeListsFile << "add_library(" << m_className << " SHARED" << std::endl;
cmakeListsFile << " " << m_className << "_global.h" << std::endl;
cmakeListsFile << " " << m_className << ".cpp" << std::endl;
cmakeListsFile << " " << m_className << ".h" << std::endl;
cmakeListsFile << " " << m_className << "_p.h" << std::endl;
cmakeListsFile << ")" << std::endl;
cmakeListsFile << std::endl;
cmakeListsFile << "set_target_properties(" << m_className << " PROPERTIES" << std::endl;
cmakeListsFile << " LIBRARY_OUTPUT_NAME \"lib" << m_className << ".so." << m_version << "\""
<< std::endl;
cmakeListsFile << " PREFIX \"\"" << std::endl;
cmakeListsFile << " SUFFIX \"\"" << std::endl;
cmakeListsFile << " SKIP_BUILD_RPATH TRUE" << std::endl;
cmakeListsFile << " BUILD_WITH_INSTALL_RPATH TRUE" << std::endl;
cmakeListsFile << ")" << std::endl;
cmakeListsFile << std::endl;
cmakeListsFile << "target_link_libraries(" << m_className << " PRIVATE" << std::endl;
cmakeListsFile << " ${XNCore_PATH}/lib/libXNCore.so" << std::endl;
cmakeListsFile << " ${XNCore_PATH}/lib/lib" << m_confName << "_Interface.so" << std::endl;
cmakeListsFile << " dl" << std::endl;
cmakeListsFile << ")" << std::endl;
cmakeListsFile << std::endl;
cmakeListsFile << "target_compile_definitions(" << m_className << " PRIVATE "
<< UpperCase(m_className) << "_LIBRARY)" << std::endl;
cmakeListsFile << std::endl;
cmakeListsFile << "if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)" << std::endl;
cmakeListsFile << " set(CMAKE_INSTALL_PREFIX \"${XNCore_PATH}/Configuration/" << m_confName
<< "/Models\" CACHE PATH \"Install path prefix\" FORCE)" << std::endl;
cmakeListsFile << "endif()" << std::endl;
cmakeListsFile << std::endl;
cmakeListsFile << "install(TARGETS " << m_className
<< " BUNDLE DESTINATION . LIBRARY DESTINATION . RUNTIME DESTINATION .)"
<< std::endl;
cmakeListsFile << std::endl;
cmakeListsFile << "file(GLOB CONFIG_FILE \"*.mcfg\")" << std::endl;
cmakeListsFile << std::endl;
cmakeListsFile << "install(FILES ${CONFIG_FILE} DESTINATION ${CMAKE_INSTALL_PREFIX} RENAME "
"\"${CMAKE_PROJECT_NAME}_V${MODEL_VERSION}.mcfg\")"
<< std::endl;
cmakeListsFile << std::endl;
cmakeListsFile.close();
return true;
}
std::string XNModelGen::GetXNCorePath()
{
const char *env_value = std::getenv("XNCore");
return env_value ? env_value : "";
}
std::string XNModelGen::UpperCase(const std::string &str)
{
std::string result = str;
std::transform(result.begin(), result.end(), result.begin(), ::toupper);
return result;
}
bool XNModelGen::IsPointer(const std::string &str)
{
return str.find("*") != std::string::npos;
}
bool XNModelGen::IsNumeric(const std::string &str)
{
return str.find("int") != std::string::npos || str.find("float") != std::string::npos
|| str.find("double") != std::string::npos || str.find("long") != std::string::npos
|| str.find("short") != std::string::npos || str.find("char") != std::string::npos
|| str.find("bool") != std::string::npos;
}
void XNModelGen::ParseStructName(const std::string &str, std::string &interfaceName,
std::string &structName)
{
try {
json j = json::parse(str);
// 遍历JSON对象第一个键作为interfaceName(数据库中的字段名)第一个值作为structName(头文件中的结构体名)
if (!j.empty() && j.is_object()) {
auto it = j.begin();
if (it != j.end()) {
interfaceName = it.key();
if (it.value().is_string()) {
structName = it.value();
}
}
}
} catch (const json::exception &e) {
// JSON解析失败将整个字符串作为structName
structName = "";
interfaceName = "";
}
}
std::vector<std::string> XNModelGen::SplitString(const std::string &str)
{
std::vector<std::string> result;
std::stringstream ss(str);
std::string token;
while (ss >> token) {
result.push_back(token);
}
return result;
}
void XNModelGen::ParseStructOriginalName(InterfaceStructInfo &structInfo)
{
std::vector<std::string> tokens = SplitString(structInfo.originalName);
if (tokens.empty()) {
return;
}
// 处理 "struct" 关键字
int startIndex = 0;
if (tokens[0] == "struct") {
startIndex = 1;
}
if (startIndex >= tokens.size()) {
return;
}
// 获取结构体类型名,检查是否包含指针符号
std::string typeToken = tokens[startIndex];
bool hasPointer = false;
std::string structType = typeToken;
// 检查类型名本身是否包含指针符号
if (typeToken.find("*") != std::string::npos) {
hasPointer = true;
// 移除指针符号,获取纯类型名
structType = typeToken;
structType.erase(std::remove(structType.begin(), structType.end(), '*'), structType.end());
}
structInfo.structType = structType;
// 获取结构体名称
std::string structName;
int nameIndex = startIndex + 1;
while (nameIndex < tokens.size()) {
std::string token = tokens[nameIndex];
// 如果当前token是单独的指针符号
if (token == "*") {
hasPointer = true;
nameIndex++;
continue;
}
// 如果当前token包含指针符号
if (token.find("*") != std::string::npos) {
hasPointer = true;
// 移除指针符号,获取结构体名称
structName = token;
structName.erase(std::remove(structName.begin(), structName.end(), '*'),
structName.end());
} else {
// 普通的结构体名称
structName = token;
}
break; // 找到结构体名称后退出
}
structInfo.isPointer = hasPointer;
structInfo.structName = structName;
structInfo.isNumeric = IsNumeric(structInfo.structType);
}