refactor: 管道截面统一存 SAT,曲线写路径退役
SectionRegionDwgOutFields 不再 explode 后按曲线写,改为固定写 nLen=0 + RegionAcisoutDwgOutFields。读取端 nLen==0 本来就识别 SAT 通道,因此 kCurrentVersionNumber 保持 7,新图在老插件上仍可还原。 同时修 SAT 通道自身缺陷: - RegionAcisoutDwgOutFields:临时文件名加进程号;new char[nLen] 补 +1 并 清零;检查短读,短读或空文件退回原生写法,不再把未初始化内存写进 DWG; acisOut/Open 失败分支补 DeleteFile;两个重复的 errorfile 分支合并为 WriteRegionNativeFallback,顺带修掉 7 字节泄漏 - RegionAcisInDwgInFields:临时文件名只取纯文件名,拒绝 DWG 里夹带的路径 成分和盘符;errorfile 分支补 delete[];create/dwgInFields/acisIn 失败 分支加日志并正确释放;acisIn 返回的非 region 实体不再泄漏 - 删除 RegionExplodeDwgOutFields(写路径退役后无调用者)
This commit is contained in:
1 parent
5692d9010b
commit
8941246b16
2 files changed
+168
-167
No files matched your search
@@ -658,6 +658,40 @@ namespace
|
||||
|
||||
return es != Acad::eOk;
|
||||
}
|
||||
|
||||
// 读端只接受纯文件名:DWG 里存的名字不可信,去掉路径成分防止写到临时目录之外
|
||||
CString SanitizeRegionTempName(const CString& sFileName)
|
||||
{
|
||||
CString sName = sFileName;
|
||||
|
||||
int nSlash = sName.ReverseFind(_T('\\'));
|
||||
int nSlash2 = sName.ReverseFind(_T('/'));
|
||||
if (nSlash2 > nSlash)
|
||||
nSlash = nSlash2;
|
||||
|
||||
if (nSlash >= 0)
|
||||
sName = sName.Mid(nSlash + 1);
|
||||
|
||||
// 空名、上跳目录、盘符一律丢弃,退回固定名
|
||||
if (sName.IsEmpty() || sName.Find(_T("..")) >= 0 || sName.Find(_T(':')) >= 0)
|
||||
sName = _T("region_tmp.dat");
|
||||
|
||||
return sName;
|
||||
}
|
||||
|
||||
// acisOut 不可用时的兜底:写 errorfile 标记,再让 region 自己写原生数据
|
||||
Acad::ErrorStatus WriteRegionNativeFallback(AcDbDwgFiler* pFiler, AcDbRegion* pRegion)
|
||||
{
|
||||
pFiler->writeString(_T("errorfile"));
|
||||
|
||||
char pszTxt[7];
|
||||
::memset(pszTxt, 0, sizeof(pszTxt));
|
||||
|
||||
pFiler->writeUInt32(7);
|
||||
pFiler->writeBytes(pszTxt, 7);
|
||||
|
||||
return pRegion->dwgOutFields(pFiler);
|
||||
}
|
||||
}
|
||||
|
||||
AcDbRegion *AecDbEwPipeBase::RegionFromCurvesDwgInFields(AcDbDwgFiler *pFiler, Adesk::UInt32 nLen)
|
||||
@@ -760,66 +794,92 @@ AcDbRegion* AecDbEwPipeBase::RegionAcisInDwgInFields(AcDbDwgFiler* pFiler)
|
||||
//高版本acis方式
|
||||
CString sFileName;
|
||||
TCHAR* pszFileName = NULL;
|
||||
pFiler->readString(&pszFileName);
|
||||
if (pszFileName != NULL)
|
||||
if (pFiler->readString(&pszFileName) != Acad::eOk || pszFileName == NULL)
|
||||
{
|
||||
//Region_%s.dat
|
||||
sFileName = pszFileName;
|
||||
acutDelString(pszFileName);
|
||||
|
||||
Adesk::UInt32 nLen = 0;
|
||||
pFiler->readUInt32(&nLen);
|
||||
|
||||
if (nLen > 0)
|
||||
{
|
||||
char* pszTxt = new char[nLen];
|
||||
pFiler->readBytes(pszTxt,nLen);
|
||||
|
||||
if (sFileName.CompareNoCase(_T("errorfile")) == 0)
|
||||
{
|
||||
//原生写法
|
||||
AcDbRegion* pRegion = (AcDbRegion*)AcDbRegion::desc()->create();
|
||||
Acad::ErrorStatus es = pRegion->dwgInFields(pFiler);
|
||||
|
||||
return pRegion;
|
||||
}
|
||||
else
|
||||
{
|
||||
CString sFullPath = FilePath::getSystemTemporaryFolder();
|
||||
sFullPath += _T("\\");
|
||||
sFullPath += sFileName;
|
||||
|
||||
CFile file;
|
||||
if (file.Open(sFullPath, CFile::modeCreate | CFile::modeWrite))
|
||||
{
|
||||
file.Write(pszTxt,nLen);
|
||||
file.Close();
|
||||
|
||||
AcDbVoidPtrArray arBodyPtrs;
|
||||
Acad::ErrorStatus es;
|
||||
if ( Acad::eOk == (es = AcDbBody::acisIn(sFullPath,arBodyPtrs) ) )
|
||||
{
|
||||
if (arBodyPtrs.length() > 0)
|
||||
{
|
||||
AcDbEntity* pEnt = (AcDbEntity*)arBodyPtrs.first();
|
||||
AcDbRegion* pRegion = AcDbRegion::cast(pEnt);
|
||||
if (pRegion != NULL)
|
||||
{
|
||||
::DeleteFile(sFullPath);
|
||||
delete[] pszTxt;
|
||||
|
||||
return pRegion;
|
||||
}
|
||||
//可能其他的合成或boolsubstract...
|
||||
}
|
||||
}
|
||||
::DeleteFile(sFullPath);
|
||||
}
|
||||
}
|
||||
delete[] pszTxt;
|
||||
}
|
||||
acutPrintf(_T("\nAecDbEwPipeBase: 截面读文件名失败。"));
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
//Region_%s.dat
|
||||
sFileName = pszFileName;
|
||||
acutDelString(pszFileName);
|
||||
|
||||
Adesk::UInt32 nLen = 0;
|
||||
pFiler->readUInt32(&nLen);
|
||||
|
||||
if (nLen == 0)
|
||||
return NULL;
|
||||
|
||||
char* pszTxt = new char[nLen + 1];
|
||||
::memset(pszTxt, 0, nLen + 1);
|
||||
pFiler->readBytes(pszTxt,nLen);
|
||||
|
||||
if (sFileName.CompareNoCase(_T("errorfile")) == 0)
|
||||
{
|
||||
//原生写法
|
||||
delete[] pszTxt;
|
||||
|
||||
AcDbRegion* pRegion = (AcDbRegion*)AcDbRegion::desc()->create();
|
||||
if (pRegion == NULL)
|
||||
{
|
||||
acutPrintf(_T("\nAecDbEwPipeBase: 截面原生读取时创建 region 失败。"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Acad::ErrorStatus es = pRegion->dwgInFields(pFiler);
|
||||
if (es != Acad::eOk)
|
||||
{
|
||||
acutPrintf(_T("\nAecDbEwPipeBase: 截面原生 dwgInFields 失败,err=%d。"),es);
|
||||
delete pRegion;
|
||||
return NULL;
|
||||
}
|
||||
return pRegion;
|
||||
}
|
||||
|
||||
CString sFullPath = FilePath::getSystemTemporaryFolder();
|
||||
sFullPath += _T("\\");
|
||||
sFullPath += SanitizeRegionTempName(sFileName);
|
||||
|
||||
CFile file;
|
||||
if (!file.Open(sFullPath, CFile::modeCreate | CFile::modeWrite))
|
||||
{
|
||||
acutPrintf(_T("\nAecDbEwPipeBase: 截面临时文件创建失败:%s"),(LPCTSTR)sFullPath);
|
||||
delete[] pszTxt;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file.Write(pszTxt,nLen);
|
||||
file.Close();
|
||||
delete[] pszTxt;
|
||||
|
||||
AcDbVoidPtrArray arBodyPtrs;
|
||||
Acad::ErrorStatus es = AcDbBody::acisIn(sFullPath,arBodyPtrs);
|
||||
if (es != Acad::eOk)
|
||||
{
|
||||
acutPrintf(_T("\nAecDbEwPipeBase: 截面 acisIn 失败,len=%u,err=%d。"),nLen,es);
|
||||
::DeleteFile(sFullPath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// acisIn 返回的实体未入库,由调用方负责释放;只留第一个 region,其余丢弃
|
||||
AcDbRegion* pRegion = NULL;
|
||||
for (int i = 0;i < arBodyPtrs.length();i++)
|
||||
{
|
||||
AcDbEntity* pEnt = (AcDbEntity*)arBodyPtrs.at(i);
|
||||
if (pRegion == NULL)
|
||||
{
|
||||
pRegion = AcDbRegion::cast(pEnt);
|
||||
if (pRegion != NULL)
|
||||
continue;
|
||||
}
|
||||
delete pEnt;
|
||||
}
|
||||
|
||||
if (pRegion == NULL)
|
||||
acutPrintf(_T("\nAecDbEwPipeBase: 截面 acisIn 未返回 region,len=%u。"),nLen);
|
||||
|
||||
::DeleteFile(sFullPath);
|
||||
return pRegion;
|
||||
}
|
||||
|
||||
AcDbRegion* AecDbEwPipeBase::SectionRegionDwgInFields(AcDbDwgFiler* pFiler,int nVer)
|
||||
@@ -1132,34 +1192,19 @@ Acad::ErrorStatus AecDbEwPipeBase::BaseCurveDwgOutFields(AcDbCurve* pBaseCurve,A
|
||||
return Acad::eOk;
|
||||
}
|
||||
|
||||
Acad::ErrorStatus AecDbEwPipeBase::RegionExplodeDwgOutFields(AcDbDwgFiler* pFiler,AcDbVoidPtrArray& arCurPtrs) const
|
||||
{
|
||||
Adesk::UInt32 nCurs = arCurPtrs.length();
|
||||
pFiler->writeUInt32(nCurs);
|
||||
|
||||
AcDbCurve* pCurve = NULL;
|
||||
for (int i = 0;i < arCurPtrs.length();i++)
|
||||
{
|
||||
pCurve = (AcDbCurve*)arCurPtrs.at(i);
|
||||
BaseCurveDwgOutFields(pCurve,pFiler);
|
||||
delete pCurve;
|
||||
}
|
||||
return Acad::eOk;
|
||||
}
|
||||
|
||||
Acad::ErrorStatus AecDbEwPipeBase::RegionAcisoutDwgOutFields(AcDbDwgFiler* pFiler) const
|
||||
{
|
||||
if (m_pRegion == NULL)
|
||||
return Acad::eInvalidInput;
|
||||
|
||||
//开始写acis方式
|
||||
//避免多文档crash
|
||||
//避免多文档crash:文件名带进程号,同一张图在两个 CAD 实例里同时打开不会互相覆盖
|
||||
TCHAR szHandleStr[19];
|
||||
memset(szHandleStr,0,sizeof(szHandleStr) );
|
||||
objectId().handle().getIntoAsciiBuffer(szHandleStr);
|
||||
|
||||
CString sFileName;
|
||||
sFileName.Format(_T("Region_%s.dat"),szHandleStr);
|
||||
sFileName.Format(_T("Region_%lu_%s.dat"),(unsigned long)::GetCurrentProcessId(),szHandleStr);
|
||||
|
||||
CString sFullPath = FilePath::getSystemTemporaryFolder();
|
||||
sFullPath += _T("\\");
|
||||
@@ -1168,110 +1213,67 @@ Acad::ErrorStatus AecDbEwPipeBase::RegionAcisoutDwgOutFields(AcDbDwgFiler* pFile
|
||||
AcDbVoidPtrArray arBodyPtrs;
|
||||
arBodyPtrs.append(m_pRegion);
|
||||
|
||||
Acad::ErrorStatus es;
|
||||
if (Acad::eOk == (es = AcDbBody::acisOut(sFullPath, arBodyPtrs)))
|
||||
Acad::ErrorStatus es = AcDbBody::acisOut(sFullPath, arBodyPtrs);
|
||||
if (Acad::eOk != es)
|
||||
{
|
||||
CFile file;
|
||||
if (file.Open(sFullPath, CFile::modeRead))
|
||||
{
|
||||
//确认REGION不会超过32位数量级字节
|
||||
//强制转换兼容可能的07-09CAD
|
||||
ULONGLONG dwFileLength = file.GetLength();
|
||||
Adesk::UInt32 nLen = (Adesk::UInt32)dwFileLength;
|
||||
|
||||
char* pszTxt = new char[nLen];
|
||||
file.Read(pszTxt, nLen);
|
||||
file.Close();
|
||||
|
||||
pFiler->writeString((LPCTSTR)sFileName);
|
||||
pFiler->writeUInt32(nLen);
|
||||
pFiler->writeBytes(pszTxt,nLen);
|
||||
|
||||
::DeleteFile(sFullPath);
|
||||
delete[] pszTxt;
|
||||
return Acad::eOk;
|
||||
}
|
||||
else
|
||||
{
|
||||
pFiler->writeString(_T("errorfile"));
|
||||
|
||||
char* pszTxt = new char[7];
|
||||
memset(pszTxt,0,7);
|
||||
|
||||
pFiler->writeUInt32(7);
|
||||
|
||||
pFiler->writeBytes(pszTxt,7);
|
||||
|
||||
//原生写法
|
||||
es = m_pRegion->dwgOutFields(pFiler);
|
||||
|
||||
return es;
|
||||
}
|
||||
acutPrintf(_T("\nAecDbEwPipeBase: 截面 acisOut 失败,handle=%s,err=%d,改用原生写法。"),szHandleStr,es);
|
||||
::DeleteFile(sFullPath);
|
||||
return WriteRegionNativeFallback(pFiler, m_pRegion);
|
||||
}
|
||||
else
|
||||
|
||||
CFile file;
|
||||
if (!file.Open(sFullPath, CFile::modeRead))
|
||||
{
|
||||
pFiler->writeString(_T("errorfile"));
|
||||
|
||||
char* pszTxt = new char[7];
|
||||
memset(pszTxt,0,7);
|
||||
|
||||
pFiler->writeUInt32(7);
|
||||
|
||||
pFiler->writeBytes(pszTxt,7);
|
||||
|
||||
//原生写法
|
||||
es = m_pRegion->dwgOutFields(pFiler);
|
||||
|
||||
return es;
|
||||
acutPrintf(_T("\nAecDbEwPipeBase: 截面临时文件打开失败,handle=%s,改用原生写法。"),szHandleStr);
|
||||
::DeleteFile(sFullPath);
|
||||
return WriteRegionNativeFallback(pFiler, m_pRegion);
|
||||
}
|
||||
return Acad::eOutOfMemory;
|
||||
|
||||
//确认REGION不会超过32位数量级字节
|
||||
//强制转换兼容可能的07-09CAD
|
||||
ULONGLONG dwFileLength = file.GetLength();
|
||||
Adesk::UInt32 nLen = (Adesk::UInt32)dwFileLength;
|
||||
|
||||
char* pszTxt = new char[nLen + 1];
|
||||
::memset(pszTxt, 0, nLen + 1);
|
||||
|
||||
UINT nRead = file.Read(pszTxt, nLen);
|
||||
file.Close();
|
||||
|
||||
if (nLen == 0 || nRead != nLen)
|
||||
{
|
||||
// 空文件或短读:尾部是未初始化内存,不能写进 DWG
|
||||
acutPrintf(_T("\nAecDbEwPipeBase: 截面临时文件异常,handle=%s,期望%u字节实读%u字节,改用原生写法。")
|
||||
,szHandleStr,nLen,nRead);
|
||||
::DeleteFile(sFullPath);
|
||||
delete[] pszTxt;
|
||||
return WriteRegionNativeFallback(pFiler, m_pRegion);
|
||||
}
|
||||
|
||||
pFiler->writeString((LPCTSTR)sFileName);
|
||||
pFiler->writeUInt32(nLen);
|
||||
pFiler->writeBytes(pszTxt,nLen);
|
||||
|
||||
::DeleteFile(sFullPath);
|
||||
delete[] pszTxt;
|
||||
return Acad::eOk;
|
||||
}
|
||||
|
||||
Acad::ErrorStatus AecDbEwPipeBase::SectionRegionDwgOutFields(AcDbDwgFiler* pFiler,int nVer) const
|
||||
{
|
||||
assertReadEnabled();
|
||||
|
||||
if (m_pRegion != NULL)
|
||||
{
|
||||
if (nVer < 4)//旧版本,保持原样,有错误漏洞
|
||||
{
|
||||
AcDbVoidPtrArray arCurPtrs;
|
||||
m_pRegion->explode(arCurPtrs);
|
||||
UNREFERENCED_PARAMETER(nVer);
|
||||
|
||||
if (!arCurPtrs.isEmpty())
|
||||
{
|
||||
return RegionExplodeDwgOutFields(pFiler,arCurPtrs);
|
||||
}
|
||||
else
|
||||
{
|
||||
//旧版本错误漏洞
|
||||
//旧版本不考虑 nVer已经升级
|
||||
//...
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AcDbVoidPtrArray arCurPtrs;
|
||||
m_pRegion->explode(arCurPtrs);
|
||||
if (m_pRegion == NULL)
|
||||
return Acad::eOk;
|
||||
|
||||
//如果炸碎成功
|
||||
if (!arCurPtrs.isEmpty())
|
||||
{
|
||||
//轻量化写法
|
||||
return RegionExplodeDwgOutFields(pFiler,arCurPtrs);
|
||||
}
|
||||
else
|
||||
{
|
||||
//补救措施,重量化写法
|
||||
//写入长度0 旧版本<4 情况不考虑 nVer已经升级
|
||||
Adesk::UInt32 nCurs = 0;
|
||||
pFiler->writeUInt32(nCurs);
|
||||
// 统一写 SAT:nLen = 0 是读取端识别 SAT 通道的标志,旧版本插件同样识别。
|
||||
// 曲线通道只用于读老图纸,写路径已退役,不再按截面类型分流
|
||||
Adesk::UInt32 nCurs = 0;
|
||||
pFiler->writeUInt32(nCurs);
|
||||
|
||||
return RegionAcisoutDwgOutFields(pFiler);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Acad::eOk;
|
||||
return RegionAcisoutDwgOutFields(pFiler);
|
||||
}
|
||||
|
||||
Acad::ErrorStatus AecDbEwPipeBase::DefaultNo()
|
||||
|
||||
@@ -149,7 +149,6 @@ protected:
|
||||
Acad::ErrorStatus BaseCurveDwgOutFields(AcDbCurve* pBaseCurve,AcDbDwgFiler* pFiler) const;
|
||||
|
||||
Acad::ErrorStatus RegionAcisoutDwgOutFields(AcDbDwgFiler* pFiler) const;
|
||||
Acad::ErrorStatus RegionExplodeDwgOutFields(AcDbDwgFiler* pFiler,AcDbVoidPtrArray& arCurPtrs) const;
|
||||
Acad::ErrorStatus SectionRegionDwgOutFields(AcDbDwgFiler* pFiler,int nVer) const;
|
||||
|
||||
Acad::ErrorStatus AddDimPoints(AcDbGripDataPtrArray& grips,const AcGeVector3d& curViewDir,
|
||||
|
||||
Reference in new issue
Block a user