chenluhua1980
2025-12-10 f71f467b68ce6c8dc6c983a2963ec9b131515441
SourceCode/Bond/Servo/HsmsPassive.cpp
@@ -228,6 +228,9 @@
int CHsmsPassive::loadVarialbles(const char* pszFilepath)
{
   m_strVariableFilepath = pszFilepath;
   m_bVariableUtf8 = false;
   m_bVariableUtf8Bom = false;
   // 先读原始字节,后续再按 UTF-8/BOM 或本地编码转换
   CFile file;
   if (!file.Open(pszFilepath, CFile::modeRead | CFile::shareDenyNone)) {
@@ -251,6 +254,8 @@
   // UTF-8 BOM
   if (nLen >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) {
      offset = 3;
      m_bVariableUtf8 = true;
      m_bVariableUtf8Bom = true;
   }
   // UTF-16 LE BOM
@@ -281,6 +286,7 @@
         MultiByteToWideChar(CP_UTF8, 0, buffer.data() + off,
            static_cast<int>(buffer.size() - off), temp.data(), need);
         content = temp.c_str();
         m_bVariableUtf8 = true;
         return true;
      };
@@ -397,6 +403,102 @@
   m_variabels.clear();
}
CStringA WideToUtf8(const CStringW& ws)
{
   int need = WideCharToMultiByte(CP_UTF8, 0, ws, -1, nullptr, 0, nullptr, nullptr);
   if (need <= 0) return "";
   CStringA out;
   LPSTR buf = out.GetBufferSetLength(need - 1);
   WideCharToMultiByte(CP_UTF8, 0, ws, -1, buf, need, nullptr, nullptr);
   out.ReleaseBuffer();
   return out;
}
CStringA WideToAnsi(const CStringW& ws)
{
   int need = WideCharToMultiByte(CP_ACP, 0, ws, -1, nullptr, 0, nullptr, nullptr);
   if (need <= 0) return "";
   CStringA out;
   LPSTR buf = out.GetBufferSetLength(need - 1);
   WideCharToMultiByte(CP_ACP, 0, ws, -1, buf, need, nullptr, nullptr);
   out.ReleaseBuffer();
   return out;
}
static CStringA AnsiToUtf8(const std::string& s)
{
   int wlen = MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, nullptr, 0);
   if (wlen <= 0) return "";
   CStringW ws;
   LPWSTR wbuf = ws.GetBufferSetLength(wlen - 1);
   MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, wbuf, wlen);
   ws.ReleaseBuffer();
   return WideToUtf8(ws);
}
int CHsmsPassive::deleteVariable(int variableId)
{
   Lock();
   auto it = std::find_if(m_variabels.begin(), m_variabels.end(), [=](SERVO::CVariable* v) {
      return v != nullptr && v->getVarialbleId() == variableId;
      });
   if (it == m_variabels.end()) {
      Unlock();
      return -1;
   }
   delete *it;
   m_variabels.erase(it);
   auto filepath = m_strVariableFilepath;
   Unlock();
   if (filepath.empty()) return -2;
   // 写回文件,保持原编码(UTF-8 或本地编码)
   CFile file;
   if (!file.Open(filepath.c_str(), CFile::modeCreate | CFile::modeWrite | CFile::shareDenyNone)) {
      return -3;
   }
   // header
   const std::string headerAnsi = "SVID,SV Name,SV Format,SV Remark\r\n";
   if (m_bVariableUtf8) {
      if (m_bVariableUtf8Bom) {
         const BYTE bom[3] = { 0xEF, 0xBB, 0xBF };
         file.Write(bom, 3);
      }
      CStringA header = AnsiToUtf8(headerAnsi);
      file.Write(header.GetString(), header.GetLength());
   }
   else {
      file.Write(headerAnsi.data(), (UINT)headerAnsi.size());
   }
   for (auto v : m_variabels) {
      if (v == nullptr) continue;
      std::string lineAnsi;
      lineAnsi.reserve(256);
      lineAnsi += std::to_string(v->getVarialbleId());
      lineAnsi.push_back(',');
      lineAnsi += v->getName();
      lineAnsi.push_back(',');
      lineAnsi += SERVO::CVariable::formatToString(v->getFormat());
      lineAnsi.push_back(',');
      lineAnsi += v->getRemark();
      lineAnsi.append("\r\n");
      if (m_bVariableUtf8) {
         CStringA outLine = AnsiToUtf8(lineAnsi);
         file.Write(outLine.GetString(), outLine.GetLength());
      }
      else {
         file.Write(lineAnsi.data(), (UINT)lineAnsi.size());
      }
   }
   file.Close();
   return 0;
}
void CHsmsPassive::setVariableValue(const char* pszName, __int64 value)
{
   auto v = getVariable(pszName);
@@ -423,30 +525,108 @@
int CHsmsPassive::loadReports(const char* pszFilepath)
{
   CStdioFile file;
   if (!file.Open(pszFilepath, CFile::modeRead)) {
   // 兼容 UTF-8/BOM 与本地编码读取
   CFile file;
   if (!file.Open(pszFilepath, CFile::modeRead | CFile::shareDenyNone)) {
      return -1;
   }
   std::regex pattern("^\\d+,\\(\\d+(,\\d+)*\\).*");  // 匹配以数字+逗号开头的字符串
   const ULONGLONG nLen = file.GetLength();
   if (nLen == 0) {
      return -1;
   }
   std::string buffer;
   buffer.resize(static_cast<size_t>(nLen));
   file.Read(buffer.data(), static_cast<UINT>(nLen));
   file.Close();
   const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buffer.data());
   size_t offset = 0;
   CStringW content;
   // UTF-8 BOM
   if (nLen >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) {
      offset = 3;
   }
   // UTF-16 LE BOM
   if (nLen >= 2 && bytes[0] == 0xFF && bytes[1] == 0xFE) {
      const wchar_t* wdata = reinterpret_cast<const wchar_t*>(buffer.data() + 2);
      const size_t wlen = (nLen - 2) / sizeof(wchar_t);
      content.SetString(wdata, static_cast<int>(wlen));
   }
   // UTF-16 BE BOM
   else if (nLen >= 2 && bytes[0] == 0xFE && bytes[1] == 0xFF) {
      const size_t wlen = (nLen - 2) / sizeof(wchar_t);
      std::wstring temp;
      temp.reserve(wlen);
      for (size_t i = 0; i < wlen; ++i) {
         wchar_t ch = static_cast<wchar_t>(bytes[2 + i * 2] << 8 | bytes[2 + i * 2 + 1]);
         temp.push_back(ch);
      }
      content = temp.c_str();
   }
   else {
      auto tryUtf8 = [&](size_t off) -> bool {
         int need = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, buffer.data() + off,
            static_cast<int>(buffer.size() - off), nullptr, 0);
         if (need <= 0) return false;
         std::wstring temp;
         temp.resize(need);
         MultiByteToWideChar(CP_UTF8, 0, buffer.data() + off,
            static_cast<int>(buffer.size() - off), temp.data(), need);
         content = temp.c_str();
         return true;
      };
      if (!tryUtf8(offset)) {
         int need = MultiByteToWideChar(CP_ACP, 0, buffer.data(), static_cast<int>(buffer.size()), nullptr, 0);
         if (need > 0) {
            std::wstring temp;
            temp.resize(need);
            MultiByteToWideChar(CP_ACP, 0, buffer.data(), static_cast<int>(buffer.size()), temp.data(), need);
            content = temp.c_str();
         }
      }
   }
   if (content.IsEmpty()) {
      return -1;
   }
   std::wregex pattern(L"^\\d+,\\(\\d+(,\\d+)*\\).*");  // 匹配以数字+逗号开头的字符串
   std::vector<SERVO::CReport*> reports;
   int index;
   CString strLine, strVariable;
   CString strId;
   while (file.ReadString(strLine)) {
      if (!std::regex_match((LPTSTR)(LPCTSTR)strLine, pattern)) {
   CStringW strLine, strVariable;
   CStringW strId;
   std::wstringstream ss(content.GetString());
   auto narrowFromW = [](const CStringW& s) -> std::string {
      int need = WideCharToMultiByte(CP_ACP, 0, s, -1, nullptr, 0, nullptr, nullptr);
      if (need <= 0) return {};
      std::string out(static_cast<size_t>(need - 1), '\0');
      WideCharToMultiByte(CP_ACP, 0, s, -1, out.data(), need, nullptr, nullptr);
      return out;
   };
   std::wstring line;
   while (std::getline(ss, line, L'\n')) {
      strLine = line.c_str();
      strLine.Trim();
      if (strLine.IsEmpty()) continue;
      if (!std::regex_match(static_cast<LPCWSTR>(strLine), pattern)) {
         continue;
      }
      index = strLine.Find(",", 0);
      index = strLine.Find(L",", 0);
      if (index < 0) continue;
      strId = strLine.Left(index);
      strVariable = strLine.Right(strLine.GetLength() - index - 1);
      strVariable.Delete(0);
      strVariable.Delete(strVariable.GetLength() - 1);
      auto vids = parseVidList(strVariable);
      CString strVariableA(narrowFromW(strVariable).c_str());
      auto vids = parseVidList(strVariableA);
      SERVO::CReport* pReport = new SERVO::CReport(atoi((LPTSTR)(LPCTSTR)strId), vids);
      SERVO::CReport* pReport = new SERVO::CReport(_wtoi(strId), vids);
      for (auto vid : vids) {
         SERVO::CVariable* pVariable = getVariable(vid);
         if (pVariable != nullptr) {
@@ -465,7 +645,6 @@
   }
   
   file.Close();
   return 0;
}
@@ -508,42 +687,122 @@
int CHsmsPassive::loadCollectionEvents(const char* pszFilepath)
{
   CStdioFile file;
   if (!file.Open(pszFilepath, CFile::modeRead)) {
   CFile file;
   if (!file.Open(pszFilepath, CFile::modeRead | CFile::shareDenyNone)) {
      return -1;
   }
   std::regex pattern("^\\d+,[^,]*,[^,]*,\\(\\d+(,\\d+)*\\).*");  // 匹配以数字+逗号开头的字符串
   const ULONGLONG nLen = file.GetLength();
   if (nLen == 0) {
      return -1;
   }
   std::string buffer;
   buffer.resize(static_cast<size_t>(nLen));
   file.Read(buffer.data(), static_cast<UINT>(nLen));
   file.Close();
   const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buffer.data());
   size_t offset = 0;
   CStringW content;
   // UTF-8 BOM
   if (nLen >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) {
      offset = 3;
   }
   // UTF-16 LE BOM
   if (nLen >= 2 && bytes[0] == 0xFF && bytes[1] == 0xFE) {
      const wchar_t* wdata = reinterpret_cast<const wchar_t*>(buffer.data() + 2);
      const size_t wlen = (nLen - 2) / sizeof(wchar_t);
      content.SetString(wdata, static_cast<int>(wlen));
   }
   // UTF-16 BE BOM
   else if (nLen >= 2 && bytes[0] == 0xFE && bytes[1] == 0xFF) {
      const size_t wlen = (nLen - 2) / sizeof(wchar_t);
      std::wstring temp;
      temp.reserve(wlen);
      for (size_t i = 0; i < wlen; ++i) {
         wchar_t ch = static_cast<wchar_t>(bytes[2 + i * 2] << 8 | bytes[2 + i * 2 + 1]);
         temp.push_back(ch);
      }
      content = temp.c_str();
   }
   else {
      auto tryUtf8 = [&](size_t off) -> bool {
         int need = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, buffer.data() + off,
            static_cast<int>(buffer.size() - off), nullptr, 0);
         if (need <= 0) return false;
         std::wstring temp;
         temp.resize(need);
         MultiByteToWideChar(CP_UTF8, 0, buffer.data() + off,
            static_cast<int>(buffer.size() - off), temp.data(), need);
         content = temp.c_str();
         return true;
      };
      if (!tryUtf8(offset)) {
         int need = MultiByteToWideChar(CP_ACP, 0, buffer.data(), static_cast<int>(buffer.size()), nullptr, 0);
         if (need > 0) {
            std::wstring temp;
            temp.resize(need);
            MultiByteToWideChar(CP_ACP, 0, buffer.data(), static_cast<int>(buffer.size()), temp.data(), need);
            content = temp.c_str();
         }
      }
   }
   if (content.IsEmpty()) {
      return -1;
   }
   std::wregex pattern(L"^\\d+,[^,]*,[^,]*,\\(\\d+(,\\d+)*\\).*");  // 匹配以数字+逗号开头的字符串
   std::vector<SERVO::CCollectionEvent*> events;
   int index, last;
   CString strLine, strRPTIDs;
   CString strId, strName, strDescription;
   while (file.ReadString(strLine)) {
      if (!std::regex_match((LPTSTR)(LPCTSTR)strLine, pattern)) {
   CStringW strLine, strRPTIDs;
   CStringW strId, strName, strDescription;
   std::wstringstream ss(content.GetString());
   auto narrowFromW = [](const CStringW& s) -> std::string {
      int need = WideCharToMultiByte(CP_ACP, 0, s, -1, nullptr, 0, nullptr, nullptr);
      if (need <= 0) return {};
      std::string out(static_cast<size_t>(need - 1), '\0');
      WideCharToMultiByte(CP_ACP, 0, s, -1, out.data(), need, nullptr, nullptr);
      return out;
   };
   std::wstring line;
   while (std::getline(ss, line, L'\n')) {
      strLine = line.c_str();
      strLine.Trim();
      if (strLine.IsEmpty()) continue;
      if (!std::regex_match(static_cast<LPCWSTR>(strLine), pattern)) {
         continue;
      }
      last = 0;
      index = strLine.Find(",", last);
      index = strLine.Find(L",", last);
      if (index < 0) continue;
      strId = strLine.Left(index);
      last = index + 1;
      index = strLine.Find(",", last);
      index = strLine.Find(L",", last);
      if (index < 0) continue;
      strName = strLine.Mid(last, index - last);
      last = index + 1;
      index = strLine.Find(",", last);
      index = strLine.Find(L",", last);
      if (index < 0) continue;
      strDescription = strLine.Mid(last, index - last);
      strRPTIDs = strLine.Right(strLine.GetLength() - index - 1);
      strRPTIDs.Delete(0);
      strRPTIDs.Delete(strRPTIDs.GetLength() - 1);
      auto prtids = parseVidList(strRPTIDs);
      CString strRPTIDsA(narrowFromW(strRPTIDs).c_str());
      auto prtids = parseVidList(strRPTIDsA);
      std::string sName = narrowFromW(strName);
      std::string sDesc = narrowFromW(strDescription);
      SERVO::CCollectionEvent* pEvent = new SERVO::CCollectionEvent(
         atoi(strId), (LPTSTR)(LPCTSTR)strName, (LPTSTR)(LPCTSTR)strDescription, prtids);
         _wtoi(strId), sName.c_str(), sDesc.c_str(), prtids);
      for (auto rptid : prtids) {
         SERVO::CReport* pReport = getReport(rptid);
         if (pReport != nullptr) {
@@ -559,9 +818,6 @@
         m_collectionEvents.push_back(item);
      }
   }
   file.Close();
   return 0;
}