Refactor DLT_Utilities to use STL containers, removing manual memory management && Add a debug output for command-line argument input
This commit is contained in:
+15
-14
@@ -1,5 +1,6 @@
|
||||
#include "Command_Solve.hpp"
|
||||
#include "DLT_Utilities.hpp"
|
||||
#include "Global_Variables.hpp"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
@@ -21,21 +22,21 @@ void Pre_Command_Solve(void)
|
||||
if (argc <= 1)
|
||||
return;
|
||||
|
||||
DLT_Type::DLT_Err err;
|
||||
// 输出测试用参数信息
|
||||
std::wstring cmd_string;
|
||||
for (int count = 0; count < argc; count++)
|
||||
{
|
||||
// int size_needed = WideCharToMultiByte(CP_UTF8, 0, argv[count], -1, NULL, 0, NULL, NULL);
|
||||
// char *strTo = (char *)malloc(size_needed);
|
||||
// WideCharToMultiByte(CP_UTF8, 0, argv[count], -1, strTo, size_needed, NULL, NULL);
|
||||
|
||||
int size_needed = WideCharToMultiByte(CP_UTF8, 0, argv[1], -1, NULL, 0, NULL, NULL);
|
||||
char *strTo = (char *)malloc(size_needed);
|
||||
WideCharToMultiByte(CP_UTF8, 0, argv[1], -1, &strTo[0], size_needed, NULL, NULL);
|
||||
// printf("Arg[%d]:%s\n", count, strTo);
|
||||
// free(strTo);
|
||||
|
||||
err = File.load_from_file(strTo);
|
||||
wchar_t Num_str[100] = {'\0'};
|
||||
wsprintf(Num_str, L"%d", count);
|
||||
cmd_string += std::wstring(L"Arg[") + Num_str + L"]:" + argv[count] + L"\n";
|
||||
}
|
||||
|
||||
DLT_Type::DLT_Msg_Node *p_list;
|
||||
File.get_msg_list(p_list);
|
||||
|
||||
free(strTo);
|
||||
|
||||
err = File.export_to_csv("test.csv");
|
||||
|
||||
if (err == DLT_Type::DLT_ERROR_NONE)
|
||||
return;
|
||||
MessageBoxW(Main_Window_hWnd, (L"[Debug] Argument input:\n" + cmd_string).c_str(), L"", MB_OK);
|
||||
}
|
||||
+261
-372
@@ -7,459 +7,296 @@ extern "C"
|
||||
#include "sys/time.h"
|
||||
}
|
||||
|
||||
// 构造函数
|
||||
DLT_Log::DLT_Log()
|
||||
/**
|
||||
* @brief 从文件加载
|
||||
* @param path_to_file 文件路径串
|
||||
* @return std::string 错误信息
|
||||
*/
|
||||
std::string DLT_Log::Load_From_File(const char *path_to_file)
|
||||
{
|
||||
// 初始化内容
|
||||
this->loaded_msg_count = 0;
|
||||
this->max_payload_len = 0;
|
||||
this->Msg_List_Head = nullptr;
|
||||
this->Msg_List_End = nullptr;
|
||||
}
|
||||
// 尝试打开文件
|
||||
FILE *pFile = fopen(path_to_file, "rb");
|
||||
if (pFile == nullptr)
|
||||
return "File \"" + std::string(path_to_file) + "\" open failed.";
|
||||
|
||||
// 析构函数
|
||||
DLT_Log::~DLT_Log()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
// 清理请求的存储并恢复初始状态
|
||||
void DLT_Log::clear(void)
|
||||
{
|
||||
|
||||
if (this->Msg_List_Head == nullptr)
|
||||
return;
|
||||
|
||||
// 释放分配的空间
|
||||
while (this->Msg_List_Head != nullptr)
|
||||
// Lambda 读取头
|
||||
auto Lambda_Read_Header = [&](DLT_Msg &Msg) -> std::string
|
||||
{
|
||||
DLT_Type::DLT_Msg_Node *p_target = this->Msg_List_Head;
|
||||
this->Msg_List_Head = this->Msg_List_Head->p_next;
|
||||
if (p_target->Msg.payload_buffer != nullptr)
|
||||
free(p_target->Msg.payload_buffer);
|
||||
free(p_target);
|
||||
}
|
||||
|
||||
// 初始化内容
|
||||
this->loaded_msg_count = 0;
|
||||
this->max_payload_len = 0;
|
||||
this->mem_use = 0;
|
||||
this->Msg_List_Head = nullptr;
|
||||
this->Msg_List_End = nullptr;
|
||||
}
|
||||
|
||||
DLT_Type::DLT_Err DLT_Log::dlt_file_read_header(FILE *p_file, DLT_Type::DLT_Msg *Msg)
|
||||
{
|
||||
if (Msg == nullptr)
|
||||
return DLT_Type::DLT_ERROR_NULL_POINTER;
|
||||
|
||||
// 存储头
|
||||
{
|
||||
|
||||
// 读取存储头
|
||||
if (fread(&(Msg->storage_header), sizeof(Msg->storage_header), 1, p_file) != 1)
|
||||
if (fread(&(Msg.storage_header), sizeof(Msg.storage_header), 1, pFile) != 1)
|
||||
{
|
||||
if (feof(p_file))
|
||||
return DLT_Type::DLT_ERROR_END_OF_FILE;
|
||||
if (feof(pFile))
|
||||
return "Unexpected EOF.";
|
||||
else
|
||||
return DLT_Type::DLT_ERROR_FILE_READ_FAILED;
|
||||
return "File read failed.";
|
||||
}
|
||||
|
||||
// 检查存储头
|
||||
if (memcmp(Msg->storage_header.pattern, "DLT\x01", 4))
|
||||
return DLT_Type::DLT_ERROR_INVALID_HEADER;
|
||||
}
|
||||
if (memcmp(Msg.storage_header.pattern, "DLT\x01", 4))
|
||||
return "Invalid storage header pattern.Must be \"DLT0x01\".";
|
||||
|
||||
// 标准头
|
||||
{
|
||||
// 读取标准头
|
||||
if (fread(&(Msg->standard_header), sizeof(Msg->standard_header), 1, p_file) != 1)
|
||||
if (fread(&(Msg.standard_header), sizeof(Msg.standard_header), 1, pFile) != 1)
|
||||
{
|
||||
if (feof(p_file))
|
||||
return DLT_Type::DLT_ERROR_INCOMPLETE_DATA;
|
||||
if (feof(pFile))
|
||||
return "Unexpected EOF.";
|
||||
else
|
||||
return DLT_Type::DLT_ERROR_FILE_READ_FAILED;
|
||||
return "File read failed.";
|
||||
}
|
||||
|
||||
// 检查标准头协议版本
|
||||
if (Msg.standard_header.htyp.VERS != 0x01)
|
||||
return "Unsupported protocol version.";
|
||||
|
||||
// 反向拼接len字段
|
||||
// [PRS_Dlt_00091] ⌈The Standard Header and the Extended Header shall be in big endian format (MSB first).⌋ (RS_LT_00016,RS_LT_00013)
|
||||
// DLT标准头是大端序,与小端序存储的uint16正好相反,所以需要反向
|
||||
{
|
||||
uint16_t len_swap;
|
||||
*((uint8_t *)&len_swap) = *(((uint8_t *)&Msg->standard_header.len) + 1);
|
||||
*(((uint8_t *)&len_swap) + 1) = *((uint8_t *)&Msg->standard_header.len);
|
||||
Msg->standard_header.len = len_swap;
|
||||
*((uint8_t *)&len_swap) = *(((uint8_t *)&Msg.standard_header.len) + 1);
|
||||
*(((uint8_t *)&len_swap) + 1) = *((uint8_t *)&Msg.standard_header.len);
|
||||
Msg.standard_header.len = len_swap;
|
||||
}
|
||||
}
|
||||
|
||||
// 消息头长度统计
|
||||
size_t msg_header_len = sizeof(Msg->standard_header);
|
||||
// 消息头长度统计
|
||||
size_t msg_header_len = sizeof(Msg.standard_header);
|
||||
|
||||
// 标准头扩展部分
|
||||
// 标准头扩展部分
|
||||
{
|
||||
// 含有额外的ECU ID
|
||||
if (Msg.standard_header.htyp.WEID)
|
||||
{
|
||||
msg_header_len += sizeof(Msg.standard_header_extra.ecu);
|
||||
|
||||
if (fread(&(Msg.standard_header_extra.ecu), sizeof(Msg.standard_header_extra.ecu), 1, pFile) != 1)
|
||||
{
|
||||
if (feof(pFile))
|
||||
return "Unexpected EOF.";
|
||||
else
|
||||
return "File read failed.";
|
||||
}
|
||||
}
|
||||
|
||||
// 含有额外的 Session ID (会话ID)
|
||||
if (Msg.standard_header.htyp.WSID)
|
||||
{
|
||||
msg_header_len += sizeof(Msg.standard_header_extra.seid);
|
||||
|
||||
if (fread(&(Msg.standard_header_extra.seid), sizeof(Msg.standard_header_extra.seid), 1, pFile) != 1)
|
||||
{
|
||||
if (feof(pFile))
|
||||
return "Unexpected EOF.";
|
||||
else
|
||||
return "File read failed.";
|
||||
}
|
||||
|
||||
// 反向拼接Session ID字段
|
||||
// [PRS_Dlt_00091] ⌈The Standard Header and the Extended Header shall be in big endian format (MSB first).⌋ (RS_LT_00016,RS_LT_00013)
|
||||
{
|
||||
uint32_t data_swap;
|
||||
|
||||
*((uint8_t *)&data_swap) = *(((uint8_t *)&Msg.standard_header_extra.seid) + 3);
|
||||
*(((uint8_t *)&data_swap) + 1) = *(((uint8_t *)&Msg.standard_header_extra.seid) + 2);
|
||||
*(((uint8_t *)&data_swap) + 2) = *(((uint8_t *)&Msg.standard_header_extra.seid) + 1);
|
||||
*(((uint8_t *)&data_swap) + 3) = *((uint8_t *)&Msg.standard_header_extra.seid);
|
||||
|
||||
Msg.standard_header_extra.seid = data_swap;
|
||||
}
|
||||
}
|
||||
|
||||
// 含有额外的 timestamp (0.1ms 自系统启动后的时间计数)
|
||||
if (Msg.standard_header.htyp.WSID)
|
||||
{
|
||||
msg_header_len += sizeof(Msg.standard_header_extra.tmsp);
|
||||
|
||||
if (fread(&(Msg.standard_header_extra.tmsp), sizeof(Msg.standard_header_extra.tmsp), 1, pFile) != 1)
|
||||
{
|
||||
if (feof(pFile))
|
||||
return "Unexpected EOF.";
|
||||
else
|
||||
return "File read failed.";
|
||||
}
|
||||
|
||||
// 反向拼接Session ID字段
|
||||
// [PRS_Dlt_00091] ⌈The Standard Header and the Extended Header shall be in big endian format (MSB first).⌋ (RS_LT_00016,RS_LT_00013)
|
||||
{
|
||||
uint32_t data_swap;
|
||||
|
||||
*((uint8_t *)&data_swap) = *(((uint8_t *)&Msg.standard_header_extra.tmsp) + 3);
|
||||
*(((uint8_t *)&data_swap) + 1) = *(((uint8_t *)&Msg.standard_header_extra.tmsp) + 2);
|
||||
*(((uint8_t *)&data_swap) + 2) = *(((uint8_t *)&Msg.standard_header_extra.tmsp) + 1);
|
||||
*(((uint8_t *)&data_swap) + 3) = *((uint8_t *)&Msg.standard_header_extra.tmsp);
|
||||
|
||||
Msg.standard_header_extra.tmsp = data_swap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 扩展头读取
|
||||
if (Msg.standard_header.htyp.UEH)
|
||||
{
|
||||
msg_header_len += sizeof(Msg.extendedheader);
|
||||
|
||||
// 读取标扩展头
|
||||
if (fread(&(Msg.extendedheader), sizeof(Msg.extendedheader), 1, pFile) != 1)
|
||||
{
|
||||
if (feof(pFile))
|
||||
return "Unexpected EOF.";
|
||||
else
|
||||
return "File read failed.";
|
||||
}
|
||||
}
|
||||
|
||||
// 分配payload空间并无错误信息返回
|
||||
Msg.payload.resize(Msg.standard_header.len - msg_header_len);
|
||||
return std::string();
|
||||
};
|
||||
|
||||
// Lambda 读取载荷
|
||||
auto Lambda_Read_Payload = [&](DLT_Msg &Msg) -> std::string
|
||||
{
|
||||
// 含有额外的ECU ID
|
||||
if (Msg->standard_header.htyp.WEID)
|
||||
if (fread(&Msg.payload[0], Msg.payload.size(), 1, pFile) != 1)
|
||||
{
|
||||
msg_header_len += sizeof(Msg->standard_header_extra.ecu);
|
||||
|
||||
if (fread(&(Msg->standard_header_extra.ecu), sizeof(Msg->standard_header_extra.ecu), 1, p_file) != 1)
|
||||
{
|
||||
if (feof(p_file))
|
||||
return DLT_Type::DLT_ERROR_INCOMPLETE_DATA;
|
||||
else
|
||||
return DLT_Type::DLT_ERROR_FILE_READ_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
// 含有额外的 Session ID (会话ID)
|
||||
if (Msg->standard_header.htyp.WSID)
|
||||
{
|
||||
msg_header_len += sizeof(Msg->standard_header_extra.seid);
|
||||
|
||||
if (fread(&(Msg->standard_header_extra.seid), sizeof(Msg->standard_header_extra.seid), 1, p_file) != 1)
|
||||
{
|
||||
if (feof(p_file))
|
||||
return DLT_Type::DLT_ERROR_INCOMPLETE_DATA;
|
||||
else
|
||||
return DLT_Type::DLT_ERROR_FILE_READ_FAILED;
|
||||
}
|
||||
|
||||
// 反向拼接Session ID字段
|
||||
// [PRS_Dlt_00091] ⌈The Standard Header and the Extended Header shall be in big endian format (MSB first).⌋ (RS_LT_00016,RS_LT_00013)
|
||||
{
|
||||
uint32_t data_swap;
|
||||
|
||||
*((uint8_t *)&data_swap) = *(((uint8_t *)&Msg->standard_header_extra.seid) + 3);
|
||||
*(((uint8_t *)&data_swap) + 1) = *(((uint8_t *)&Msg->standard_header_extra.seid) + 2);
|
||||
*(((uint8_t *)&data_swap) + 2) = *(((uint8_t *)&Msg->standard_header_extra.seid) + 1);
|
||||
*(((uint8_t *)&data_swap) + 3) = *((uint8_t *)&Msg->standard_header_extra.seid);
|
||||
|
||||
Msg->standard_header_extra.seid = data_swap;
|
||||
}
|
||||
}
|
||||
|
||||
// 含有额外的 timestamp (0.1ms 自系统启动后的时间计数)
|
||||
if (Msg->standard_header.htyp.WSID)
|
||||
{
|
||||
msg_header_len += sizeof(Msg->standard_header_extra.tmsp);
|
||||
|
||||
if (fread(&(Msg->standard_header_extra.tmsp), sizeof(Msg->standard_header_extra.tmsp), 1, p_file) != 1)
|
||||
{
|
||||
if (feof(p_file))
|
||||
return DLT_Type::DLT_ERROR_INCOMPLETE_DATA;
|
||||
else
|
||||
return DLT_Type::DLT_ERROR_FILE_READ_FAILED;
|
||||
}
|
||||
|
||||
// 反向拼接Session ID字段
|
||||
// [PRS_Dlt_00091] ⌈The Standard Header and the Extended Header shall be in big endian format (MSB first).⌋ (RS_LT_00016,RS_LT_00013)
|
||||
{
|
||||
uint32_t data_swap;
|
||||
|
||||
*((uint8_t *)&data_swap) = *(((uint8_t *)&Msg->standard_header_extra.tmsp) + 3);
|
||||
*(((uint8_t *)&data_swap) + 1) = *(((uint8_t *)&Msg->standard_header_extra.tmsp) + 2);
|
||||
*(((uint8_t *)&data_swap) + 2) = *(((uint8_t *)&Msg->standard_header_extra.tmsp) + 1);
|
||||
*(((uint8_t *)&data_swap) + 3) = *((uint8_t *)&Msg->standard_header_extra.tmsp);
|
||||
|
||||
Msg->standard_header_extra.tmsp = data_swap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 扩展头读取
|
||||
if (Msg->standard_header.htyp.UEH)
|
||||
{
|
||||
msg_header_len += sizeof(Msg->extendedheader);
|
||||
|
||||
// 读取标扩展头
|
||||
if (fread(&(Msg->extendedheader), sizeof(Msg->extendedheader), 1, p_file) != 1)
|
||||
{
|
||||
if (feof(p_file))
|
||||
return DLT_Type::DLT_ERROR_INCOMPLETE_DATA;
|
||||
if (feof(pFile))
|
||||
return "Unexpected EOF.";
|
||||
else
|
||||
return DLT_Type::DLT_ERROR_FILE_READ_FAILED;
|
||||
return "File read failed.";
|
||||
}
|
||||
}
|
||||
|
||||
// 计算Payload长度
|
||||
Msg->payload_length = Msg->standard_header.len - msg_header_len;
|
||||
return std::string();
|
||||
};
|
||||
|
||||
return DLT_Type::DLT_ERROR_NONE;
|
||||
}
|
||||
|
||||
DLT_Type::DLT_Err DLT_Log::dlt_file_read_payload(FILE *p_file, DLT_Type::DLT_Msg *Msg)
|
||||
{
|
||||
if (Msg == nullptr)
|
||||
return DLT_Type::DLT_ERROR_NULL_POINTER;
|
||||
|
||||
if (Msg->payload_length == 0)
|
||||
// 错误信息串
|
||||
std::string err_str;
|
||||
// 循环解析文件
|
||||
while (true)
|
||||
{
|
||||
Msg->payload_buffer = nullptr;
|
||||
return DLT_Type::DLT_ERROR_NONE;
|
||||
}
|
||||
DLT_Msg Msg = {0};
|
||||
|
||||
// 读取Payload
|
||||
Msg->payload_buffer = (uint8_t *)malloc(Msg->payload_length);
|
||||
this->mem_use += Msg->payload_length;
|
||||
err_str = Lambda_Read_Header(Msg);
|
||||
if (!err_str.empty())
|
||||
break;
|
||||
|
||||
if (Msg->payload_buffer == nullptr)
|
||||
return DLT_Type::DLT_ERROR_MEM_ALLOCATE_FAILED;
|
||||
if (Msg.payload.size() > 0)
|
||||
err_str = Lambda_Read_Payload(Msg);
|
||||
|
||||
if (fread(Msg->payload_buffer, Msg->payload_length, 1, p_file) != 1)
|
||||
{
|
||||
free(Msg->payload_buffer);
|
||||
this->mem_use -= Msg->payload_length;
|
||||
Msg->payload_buffer = nullptr;
|
||||
|
||||
if (feof(p_file))
|
||||
return DLT_Type::DLT_ERROR_INCOMPLETE_DATA;
|
||||
if (err_str.empty() == true)
|
||||
{
|
||||
if (Msg.payload.size() > this->private_max_payload_len)
|
||||
this->private_max_payload_len = Msg.payload.size();
|
||||
this->private_msg_list.push_back(Msg);
|
||||
}
|
||||
else
|
||||
return DLT_Type::DLT_ERROR_FILE_READ_FAILED;
|
||||
break;
|
||||
|
||||
// 读取结束判定
|
||||
if (fgetc(pFile) == EOF)
|
||||
break;
|
||||
else
|
||||
fseek(pFile, -1, SEEK_CUR);
|
||||
}
|
||||
|
||||
return ::DLT_Type::DLT_ERROR_NONE;
|
||||
fclose(pFile);
|
||||
return err_str;
|
||||
}
|
||||
|
||||
DLT_Type::DLT_Err DLT_Log::load_from_file(const char *file_name_str)
|
||||
/**
|
||||
* @brief 以CSV格式导出到文件
|
||||
* @param path_to_file 文件路径串
|
||||
* @return std::string 错误信息
|
||||
*/
|
||||
std::string DLT_Log::Export_CSV(const char *path_to_file)
|
||||
{
|
||||
// 打开文件
|
||||
FILE *p_file = fopen(file_name_str, "rb");
|
||||
if (p_file == nullptr)
|
||||
return DLT_Type::DLT_ERROR_FILE_OPEN_FAILED;
|
||||
|
||||
// 解析消息内容
|
||||
{
|
||||
DLT_Type::DLT_Err err = DLT_Type::DLT_ERROR_NONE;
|
||||
while (1)
|
||||
{
|
||||
DLT_Type::DLT_Msg Msg = {0};
|
||||
|
||||
err = dlt_file_read_header(p_file, &Msg);
|
||||
if (err != DLT_Type::DLT_ERROR_NONE)
|
||||
{
|
||||
if (err == DLT_Type::DLT_ERROR_END_OF_FILE)
|
||||
break;
|
||||
fclose(p_file);
|
||||
return err;
|
||||
}
|
||||
err = dlt_file_read_payload(p_file, &Msg);
|
||||
if (err != DLT_Type::DLT_ERROR_NONE)
|
||||
{
|
||||
fclose(p_file);
|
||||
return err;
|
||||
}
|
||||
|
||||
DLT_Type::DLT_Msg_Node *p_target_msg = (DLT_Type::DLT_Msg_Node *)malloc(sizeof(DLT_Type::DLT_Msg_Node));
|
||||
this->mem_use += sizeof(DLT_Type::DLT_Msg_Node);
|
||||
if (p_target_msg == nullptr)
|
||||
{
|
||||
this->mem_use -= sizeof(DLT_Type::DLT_Msg_Node);
|
||||
fclose(p_file);
|
||||
return DLT_Type::DLT_ERROR_MEM_ALLOCATE_FAILED;
|
||||
}
|
||||
p_target_msg->p_next = nullptr;
|
||||
p_target_msg->Msg = Msg;
|
||||
|
||||
if (this->Msg_List_Head == nullptr)
|
||||
{
|
||||
this->Msg_List_Head = this->Msg_List_End = p_target_msg;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->Msg_List_End->p_next = p_target_msg;
|
||||
this->Msg_List_End = p_target_msg;
|
||||
}
|
||||
|
||||
// 统计最长长度
|
||||
if (Msg.payload_length > this->max_payload_len)
|
||||
this->max_payload_len = Msg.payload_length;
|
||||
|
||||
this->loaded_msg_count++;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(p_file);
|
||||
return DLT_Type::DLT_ERROR_NONE;
|
||||
}
|
||||
|
||||
size_t DLT_Log::get_msg_list(DLT_Type::DLT_Msg_Node *(&p_msg_list))
|
||||
{
|
||||
if (this->loaded_msg_count != 0)
|
||||
p_msg_list = this->Msg_List_Head;
|
||||
else
|
||||
p_msg_list = nullptr;
|
||||
|
||||
return this->loaded_msg_count;
|
||||
}
|
||||
|
||||
DLT_Type::DLT_Err DLT_Log::sort_msg_list(void)
|
||||
{
|
||||
// 临时分配的排序用指针数组
|
||||
DLT_Type::DLT_Msg_Node **Node_P_Arr = (DLT_Type::DLT_Msg_Node **)malloc(sizeof(DLT_Type::DLT_Msg_Node *) * this->loaded_msg_count);
|
||||
if (Node_P_Arr == nullptr)
|
||||
return DLT_Type::DLT_ERROR_MEM_ALLOCATE_FAILED;
|
||||
|
||||
// 填充地址数组
|
||||
{
|
||||
DLT_Type::DLT_Msg_Node *p_target_node = this->Msg_List_Head;
|
||||
for (size_t count = 0; count < loaded_msg_count; count++)
|
||||
{
|
||||
Node_P_Arr[count] = p_target_node;
|
||||
p_target_node = p_target_node->p_next;
|
||||
}
|
||||
}
|
||||
|
||||
// qsort排序
|
||||
qsort(Node_P_Arr,
|
||||
loaded_msg_count,
|
||||
sizeof(DLT_Type::DLT_Msg_Node *),
|
||||
|
||||
// 升序,小时间戳在前
|
||||
[](const void *param1, const void *param2) -> int
|
||||
{
|
||||
DLT_Type::DLT_Msg_Node *Node1 = *(DLT_Type::DLT_Msg_Node **)param1;
|
||||
DLT_Type::DLT_Msg_Node *Node2 = *(DLT_Type::DLT_Msg_Node **)param2;
|
||||
if (Node1->Msg.storage_header.seconds > Node2->Msg.storage_header.seconds)
|
||||
return 1;
|
||||
else if (Node1->Msg.storage_header.seconds == Node2->Msg.storage_header.seconds)
|
||||
{
|
||||
if (Node1->Msg.storage_header.microseconds > Node2->Msg.storage_header.microseconds)
|
||||
return 1;
|
||||
else if (Node1->Msg.storage_header.microseconds == Node2->Msg.storage_header.microseconds)
|
||||
{
|
||||
// 存在0.1ms时间戳
|
||||
if (Node1->Msg.standard_header.htyp.WTMS && Node2->Msg.standard_header.htyp.WTMS)
|
||||
{
|
||||
if (Node1->Msg.standard_header_extra.tmsp > Node2->Msg.standard_header_extra.tmsp)
|
||||
return 1;
|
||||
else if (Node1->Msg.standard_header_extra.tmsp == Node2->Msg.standard_header_extra.tmsp)
|
||||
return 0;
|
||||
else if (Node1->Msg.standard_header_extra.tmsp < Node2->Msg.standard_header_extra.tmsp)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
// 重新连接消息列表
|
||||
{
|
||||
this->Msg_List_Head = Node_P_Arr[0];
|
||||
this->Msg_List_End = Node_P_Arr[this->loaded_msg_count - 1];
|
||||
this->Msg_List_End->p_next = nullptr;
|
||||
|
||||
DLT_Type::DLT_Msg_Node *p_target = Node_P_Arr[0];
|
||||
for (size_t count = 1; count < this->loaded_msg_count; count++)
|
||||
{
|
||||
p_target->p_next = Node_P_Arr[count];
|
||||
p_target = p_target->p_next;
|
||||
}
|
||||
}
|
||||
|
||||
// 释放空间
|
||||
free(Node_P_Arr);
|
||||
return DLT_Type::DLT_ERROR_NONE;
|
||||
}
|
||||
|
||||
DLT_Type::DLT_Err DLT_Log::export_to_csv(const char *file_name_str)
|
||||
{
|
||||
FILE *p_file = fopen(file_name_str, "wb");
|
||||
if (p_file == nullptr)
|
||||
return DLT_Type::DLT_ERROR_FILE_CREATE_FAILED;
|
||||
// 尝试打开文件
|
||||
FILE *pFile = fopen(path_to_file, "wb");
|
||||
if (pFile == nullptr)
|
||||
return "File \"" + std::string(path_to_file) + "\" open failed.";
|
||||
|
||||
// 打印首行
|
||||
{
|
||||
fprintf(p_file, "Index,Date&Time(Local),Timestamp,Count,ECU ID,Application ID,Context ID ,Session ID,Type,Sub Type,Mode,#Args,Payload,");
|
||||
fprintf(pFile, "Index,Date&Time(Local),Timestamp,Count,ECU ID,Application ID,Context ID ,Session ID,Type,Sub Type,Mode,#Args,Payload,");
|
||||
|
||||
for (size_t count = 0; count < this->max_payload_len; count++)
|
||||
fprintf(p_file, "B%d,", count);
|
||||
fseek(p_file, -1, SEEK_CUR);
|
||||
fprintf(p_file, "\r\n");
|
||||
fprintf(pFile, "B%d,", count);
|
||||
fseek(pFile, -1, SEEK_CUR);
|
||||
fprintf(pFile, "\r\n");
|
||||
}
|
||||
|
||||
// 遍历每行数据
|
||||
DLT_Type::DLT_Msg_Node *p_msg = this->Msg_List_Head;
|
||||
for (size_t line_count = 0; line_count < this->loaded_msg_count; line_count++)
|
||||
size_t line_count = 0;
|
||||
for (auto Msg : this->private_msg_list)
|
||||
{
|
||||
|
||||
// 输出索引号
|
||||
fprintf(p_file, "%d,", line_count);
|
||||
fprintf(pFile, "%d,", line_count);
|
||||
|
||||
// 输出日期和时间
|
||||
{
|
||||
time_t timestamp = (time_t)p_msg->Msg.storage_header.seconds;
|
||||
time_t timestamp = (time_t)Msg.storage_header.seconds;
|
||||
struct tm *time_struct = localtime(×tamp);
|
||||
char time_str[100] = {'\0'};
|
||||
// 格式化为 "YY/MM/DD HH:MM:SS"
|
||||
strftime(time_str, sizeof(time_str), "%Y/%m/%d %H:%M:%S", time_struct);
|
||||
fprintf(p_file, "%s.%d,", time_str, p_msg->Msg.storage_header.microseconds);
|
||||
fprintf(pFile, "%s.%d,", time_str, Msg.storage_header.microseconds);
|
||||
}
|
||||
|
||||
// 输出头附加信息
|
||||
{
|
||||
// 存在扩展时间戳
|
||||
if (p_msg->Msg.standard_header.htyp.WTMS)
|
||||
if (Msg.standard_header.htyp.WTMS)
|
||||
{
|
||||
/**< Timestamp since system start in 0.1 milliseconds */
|
||||
char time_str[20];
|
||||
sprintf(time_str, "%d", p_msg->Msg.standard_header_extra.tmsp);
|
||||
sprintf(time_str, "%d", Msg.standard_header_extra.tmsp);
|
||||
if (strlen(time_str) > 4)
|
||||
{
|
||||
char *p_sec_end = time_str + strlen(time_str) - 4;
|
||||
|
||||
// 输出秒
|
||||
for (char *p = time_str; p < p_sec_end; p++)
|
||||
fputc(*p, p_file);
|
||||
fputc(*p, pFile);
|
||||
// 输出剩余的时间
|
||||
fprintf(p_file, ".%s,", p_sec_end);
|
||||
fprintf(pFile, ".%s,", p_sec_end);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(p_file, "0.");
|
||||
fprintf(pFile, "0.");
|
||||
for (int count = 4 - strlen(time_str); count > 0; count--)
|
||||
fputc('0', p_file);
|
||||
fprintf(p_file, "%s,", time_str);
|
||||
fputc('0', pFile);
|
||||
fprintf(pFile, "%s,", time_str);
|
||||
}
|
||||
}
|
||||
else
|
||||
fprintf(p_file, "N/A,");
|
||||
fprintf(pFile, "N/A,");
|
||||
|
||||
// 消息计数
|
||||
fprintf(p_file, "%d,", p_msg->Msg.standard_header.mcnt);
|
||||
fprintf(pFile, "%d,", Msg.standard_header.mcnt);
|
||||
|
||||
// 存在扩展ECU ID
|
||||
if (p_msg->Msg.standard_header.htyp.WEID)
|
||||
fprintf(p_file, "%.4s,", p_msg->Msg.standard_header_extra.ecu);
|
||||
if (Msg.standard_header.htyp.WEID)
|
||||
fprintf(pFile, "%.4s,", Msg.standard_header_extra.ecu);
|
||||
else
|
||||
fprintf(p_file, "%.4s,", p_msg->Msg.storage_header.ecu);
|
||||
fprintf(pFile, "%.4s,", Msg.storage_header.ecu);
|
||||
|
||||
// 输出 Apid 和 Ctid
|
||||
if (p_msg->Msg.standard_header.htyp.UEH)
|
||||
if (Msg.standard_header.htyp.UEH)
|
||||
{
|
||||
fprintf(p_file, "%.4s,", p_msg->Msg.extendedheader.apid);
|
||||
fprintf(p_file, "%.4s,", p_msg->Msg.extendedheader.ctid);
|
||||
fprintf(pFile, "%.4s,", Msg.extendedheader.apid);
|
||||
fprintf(pFile, "%.4s,", Msg.extendedheader.ctid);
|
||||
}
|
||||
else
|
||||
{
|
||||
// skip apid && ctid
|
||||
fprintf(p_file, "N/A,N/A,");
|
||||
fprintf(pFile, "N/A,N/A,");
|
||||
}
|
||||
|
||||
// 存在 Session ID
|
||||
if (p_msg->Msg.standard_header.htyp.WSID)
|
||||
fprintf(p_file, "%d,", p_msg->Msg.standard_header_extra.seid);
|
||||
if (Msg.standard_header.htyp.WSID)
|
||||
fprintf(pFile, "%d,", Msg.standard_header_extra.seid);
|
||||
else
|
||||
fprintf(p_file, "N/A,");
|
||||
fprintf(pFile, "N/A,");
|
||||
|
||||
// 输出 Type 、Subtype 、Mode 、#Args
|
||||
if (p_msg->Msg.standard_header.htyp.UEH)
|
||||
if (Msg.standard_header.htyp.UEH)
|
||||
{
|
||||
const char *Type_str[] = {"log", "trace", "network", "control"};
|
||||
const char *SubType_Str[][0xF] = {
|
||||
@@ -474,31 +311,83 @@ DLT_Type::DLT_Err DLT_Log::export_to_csv(const char *file_name_str)
|
||||
};
|
||||
|
||||
// Type && Subtype
|
||||
fprintf(p_file, "%s,", Type_str[p_msg->Msg.extendedheader.msin.MSTP]);
|
||||
fprintf(p_file, "%s,", SubType_Str[p_msg->Msg.extendedheader.msin.MSTP][(p_msg->Msg.extendedheader.msin.MTIN - 1) % 0xF]);
|
||||
fprintf(pFile, "%s,", Type_str[Msg.extendedheader.msin.MSTP]);
|
||||
fprintf(pFile, "%s,", SubType_Str[Msg.extendedheader.msin.MSTP][(Msg.extendedheader.msin.MTIN - 1) % 0xF]);
|
||||
|
||||
// Mode && #Args
|
||||
fprintf(p_file, "%s,", p_msg->Msg.extendedheader.msin.VERB ? "verbose" : "non-verbose");
|
||||
fprintf(p_file, "%d,", p_msg->Msg.extendedheader.noar);
|
||||
fprintf(pFile, "%s,", Msg.extendedheader.msin.VERB ? "verbose" : "non-verbose");
|
||||
fprintf(pFile, "%d,", Msg.extendedheader.noar);
|
||||
}
|
||||
else
|
||||
fprintf(p_file, "N/A,N/A,N/A,N/A,");
|
||||
fprintf(pFile, "N/A,N/A,N/A,N/A,");
|
||||
}
|
||||
|
||||
// Payload概览行
|
||||
fprintf(p_file, ",");
|
||||
// Payload概览列跳过
|
||||
fprintf(pFile, ",");
|
||||
|
||||
// 逐个打印 Payload
|
||||
for (size_t count = 0; count < p_msg->Msg.payload_length; count++)
|
||||
fprintf(p_file, "%0X,", p_msg->Msg.payload_buffer[count]);
|
||||
for (auto data_byte : Msg.payload)
|
||||
fprintf(pFile, "%0X,", data_byte);
|
||||
|
||||
fseek(p_file, -1, SEEK_CUR);
|
||||
fprintf(p_file, "\r\n");
|
||||
|
||||
p_msg = p_msg->p_next;
|
||||
// 结束行
|
||||
fseek(pFile, -1, SEEK_CUR);
|
||||
fprintf(pFile, "\r\n");
|
||||
line_count++;
|
||||
}
|
||||
|
||||
fclose(p_file);
|
||||
fclose(pFile);
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return DLT_Type::DLT_ERROR_NONE;
|
||||
// 对消息列表进行排序
|
||||
void DLT_Log::Sort(void)
|
||||
{
|
||||
// Quick Sort
|
||||
qsort(&this->private_msg_list[0],
|
||||
this->private_msg_list.size(),
|
||||
sizeof(this->private_msg_list[0]),
|
||||
[](const void *param1, const void *param2) -> int
|
||||
{
|
||||
const DLT_Msg *pMsg1 = (const DLT_Msg *)param1;
|
||||
const DLT_Msg *pMsg2 = (const DLT_Msg *)param2;
|
||||
|
||||
if (pMsg1->storage_header.seconds > pMsg2->storage_header.seconds)
|
||||
return 1;
|
||||
else if (pMsg1->storage_header.seconds == pMsg2->storage_header.seconds)
|
||||
{
|
||||
if (pMsg1->storage_header.microseconds > pMsg2->storage_header.microseconds)
|
||||
return 1;
|
||||
else if (pMsg1->storage_header.microseconds == pMsg2->storage_header.microseconds)
|
||||
{
|
||||
// 存在0.1ms时间戳
|
||||
if (pMsg1->standard_header.htyp.WTMS && pMsg2->standard_header.htyp.WTMS)
|
||||
{
|
||||
if (pMsg1->standard_header_extra.tmsp > pMsg2->standard_header_extra.tmsp)
|
||||
return 1;
|
||||
else if (pMsg1->standard_header_extra.tmsp == pMsg2->standard_header_extra.tmsp)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
// 清除缓存的信息
|
||||
void DLT_Log::Clear(void)
|
||||
{
|
||||
this->private_max_payload_len = 0;
|
||||
|
||||
// 清空内容
|
||||
std::vector<DLT_Msg> empty_list;
|
||||
this->private_msg_list.swap(empty_list);
|
||||
}
|
||||
+26
-19
@@ -409,38 +409,45 @@ void Widgets::Control_Panel(const ImVec2 &size)
|
||||
[&]()
|
||||
{
|
||||
DLT_Log Log;
|
||||
std::string err_str;
|
||||
|
||||
Input_File_Node *p_file_list = input_dlt_file_list_head;
|
||||
DLT_Type::DLT_Err err;
|
||||
|
||||
while (p_file_list != nullptr)
|
||||
{
|
||||
err = Log.load_from_file(p_file_list->file_name_str);
|
||||
if (err != DLT_Type::DLT_ERROR_NONE)
|
||||
err_str = Log.Load_From_File(p_file_list->file_name_str);
|
||||
if (!err_str.empty())
|
||||
break;
|
||||
p_file_list = p_file_list->p_next;
|
||||
}
|
||||
|
||||
if (err != DLT_Type::DLT_ERROR_NONE)
|
||||
if (err_str.empty())
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
case DLT_Type::DLT_ERROR_FILE_OPEN_FAILED: // 文件打开失败
|
||||
MessageBoxW(Main_Window_hWnd, L"文件打开失败,检查路径是否存在特殊字符", L"", MB_OK | MB_ICONERROR);
|
||||
break;
|
||||
default:
|
||||
MessageBoxW(Main_Window_hWnd, L"文件加载失败", L"", MB_OK | MB_ICONERROR);
|
||||
}
|
||||
Log.Sort();
|
||||
err_str = Log.Export_CSV(export_file_path_str);
|
||||
}
|
||||
|
||||
if (err_str.empty())
|
||||
{
|
||||
MessageBoxW(Main_Window_hWnd, L"导出完成", L"", MB_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 排序后导出
|
||||
Log.sort_msg_list();
|
||||
err = Log.export_to_csv(export_file_path_str);
|
||||
// 工具Lambda string 转 wstring
|
||||
auto Lambda_String_To_WString = [](const std::string &str) -> std::wstring
|
||||
{
|
||||
if (str.empty())
|
||||
return std::wstring();
|
||||
int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), nullptr, 0);
|
||||
if (len <= 0)
|
||||
return std::wstring();
|
||||
std::wstring wstr(len, L'\0');
|
||||
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), &wstr[0], len);
|
||||
return wstr;
|
||||
};
|
||||
|
||||
if (err == DLT_Type::DLT_ERROR_NONE)
|
||||
MessageBoxW(Main_Window_hWnd, L"导出完成", L"", MB_OK);
|
||||
else
|
||||
MessageBoxW(Main_Window_hWnd, L"导出失败,检查文件占用", L"", MB_OK | MB_ICONERROR);
|
||||
// 输出错误信息
|
||||
MessageBoxW(Main_Window_hWnd, (L"导出失败\n" + Lambda_String_To_WString(err_str)).c_str(), L"", MB_OK | MB_ICONERROR);
|
||||
}
|
||||
export_confirmed = false;
|
||||
export_task_created = false;
|
||||
|
||||
Reference in New Issue
Block a user