Files
envi-code/SourceCode/Code2026/inc/AecDbObjXDataMap.h
T
company-desktop-computer 199abb989c 重构: AecDbObjXDataMap 解耦 UI,并统一 SetAt/数组实现
- AecXData 的 ctor/Free/CopyFrom 由头部 inline 移入 .cpp,结构体加
  AECDLLIMPEXP 导出,修复其它模块构造 AecXData 时的 LNK2019。
- 抽出私有 SetXData(pszKey, xdata) 助手,替换各 SetAt 中重复的
  find/Free+覆盖/insert 逻辑,并接管 xdata 所有权。
- 数组二进制块统一为 [kArrayMagic][元素类型][元素个数][数据...],元素类型
  复用 AecXData::EType;新增元素类型无需再加魔数或类型标签。
- 矩阵/数组魔数集中到 .cpp 顶部常量,便于维护。
- List(CListCtrl*, int) 改为 List(std::vector<CString>&):去掉 MFC 控件与
  nImage 依赖,每个元素输出 key/value 两项;CCKSXDlg::ListXDataMap 相应改为
  构造 vector 后填充两列列表。
2026-10-13 15:28:19 +08:00

288 lines
9.7 KiB
C++

#ifndef _AECDBOBJXDATAMAP_H__
#define _AECDBOBJXDATAMAP_H__
#if _MSC_VER > 1000
#pragma once
#endif
#include <map>
#include "dbfiler.h"
#include "shJson.h"
#include <wtypes.h> // VARENUM / VT_* ,供 AecXData::EType 使用
#ifdef AECRXBASE_EXPORT
#define AECDLLIMPEXP __declspec(dllexport)
#else
#define AECDLLIMPEXP __declspec(dllimport)
#endif
#define XData_Func_Const(ent_ptr, func_name, ...)\
{\
if ((ent_ptr))\
{\
const AecDbObjXDataMap *pMap((ent_ptr)->GetSpecialtyData());\
if (pMap) pMap->##func_name(##__VA_ARGS__);\
}\
}
#define XData_Func(ent_ptr, func_name, ...)\
{\
if ((ent_ptr))\
{\
AecDbObjXDataMap *pMap((ent_ptr)->GetSpecialtyData());\
if (pMap) pMap->##func_name(##__VA_ARGS__);\
}\
}
typedef std::pair<CString, CString> SH_BIM_REC;
typedef std::vector<SH_BIM_REC> SH_BIM_BLOCK;
// AecXData 会被其它模块(CoreLibrary / 各 Cmd)直接构造使用,必须随 AecRxBase 一起导出,
// 否则成员函数定义在 .cpp 里时其它模块会 LNK2019(unresolved external symbol)。
typedef struct AECDLLIMPEXP AecXData
{
// 数据类型标签(nVt)。直接用 wtypes.h 的 VARENUM(VT_*) 组合来表达,直观且与
// 原实现逐位一致;nVt 会写入 DWG/DXF/XData,改数值会破坏旧图兼容,务必保持不变。
enum EType
{
kTypeShort = VT_I2, // short
kTypeInt = VT_I4, // int
kTypeDouble = VT_R8, // double
kTypeString = VT_BSTR, // TCHAR* 字符串
kTypeSoftId = VT_UI4, // AcDbObjectId 软指针
kTypeInt64 = VT_I8, // 历史遗留(仅读)
kTypeHardId = VT_UI8, // AcDbObjectId 硬指针
kTypePoint = (VT_BYREF | VT_R8), // 点,不随实体变换
kTypePointWorld = (VT_BYREF | VT_R8) + 1, // 点,随实体变换
kTypeVector = (VT_BYREF | VT_R8) + 2, // 向量,不随实体变换
kTypeVectorWorld = (VT_BYREF | VT_R8) + 3, // 向量,随实体变换
kTypeMatrix = (VT_BYREF | VT_R8) + 4, // 矩阵(16个double,二进制块,128字节)
kTypeBinary = (VT_BYREF | VT_R8) + 5, // 二进制块
};
int nVt;
LONG_PTR npszLen; //对应字符数据长度
union
{
short iVal; // short型
LONG_PTR nVal; // 整型数据
double dVal[3]; // 浮点数据
TCHAR* pszVal; // 字符数据
void* pData; // binary data
};
// 1. 默认构造函数,替代原有代码中散落的 memset(&xdata, 0, sizeof(xdata));
// 实现见 AecDbObjXDataMap.cpp(随本 DLL 导出,其它模块可直接构造)。
AecXData();
// 2. 核心清理函数
void Free();
// 3. 深拷贝:先释放自身已持有的资源,再从 src 深拷贝。
// 字符串/矩阵/二进制会重新分配内存,不与 src 共享缓冲;
// 支持类型变化(nVt 不同也照常覆盖)。this == &src 时直接返回。
bool CopyFrom(const AecXData &src);
}AECXDATA;
class AECDLLIMPEXP AecDbObjXDataMap
{
private:
static const int g_nVersion;
public:
AecDbObjXDataMap();
AecDbObjXDataMap(const AecDbObjXDataMap& datamap);
virtual ~AecDbObjXDataMap();
// 把 kTypeMatrix 的 16 个 double 二进制块格式化为逗号分隔文本(供显示/比较使用)
static CString MatrixToString(const AecXData& xdata);
public:
BOOL SetAt(LPCTSTR pszKey, const int &nVal);
BOOL SetAt(LPCTSTR pszKey, const DWORD &dw);
BOOL SetAt(LPCTSTR pszKey, const Adesk::Int16 &nVal);
BOOL SetAt(LPCTSTR pszKey, const double &dVal);
BOOL SetAt(LPCTSTR pszKey,const AcGeDoubleArray& arVal);
BOOL SetAt(LPCTSTR pszKey,const AcGeVector3d& vt,BOOL bTransformBy = FALSE);
BOOL SetAt(LPCTSTR pszKey,const AcGePoint3d& ptGe,BOOL bTransformBy = FALSE);
BOOL SetAt(LPCTSTR pszKey,const AcGePoint3dArray& arPt,BOOL bTransformBy = FALSE);
BOOL SetAt(LPCTSTR pszKey,LPCTSTR pszValue);
BOOL SetAt(LPCTSTR pszKey,const AcDbObjectId& id,BOOL bIsSoft = TRUE);
BOOL SetAt(LPCTSTR pszKey,const AcDbHandle& handle);
BOOL SetAt(LPCTSTR pszKey,const AcGeMatrix3d& xform);
BOOL SetAt(LPCTSTR pszKey,void* pData,int nSize);
BOOL SetAt(LPCTSTR pszKey, const AecDbObjXDataMap& xDataMap);
BOOL GetAt(LPCTSTR pszKey, AecDbObjXDataMap& xDataMap);
BOOL GetAt(LPCTSTR pszKey,void*& pData,int& nSize) const;
BOOL GetAt(LPCTSTR pszKey,int& nVal) const;
BOOL GetAt(LPCTSTR pszKey, short &nVal) const;
BOOL GetAt(LPCTSTR pszKey, DWORD &dw) const;
BOOL GetAt(LPCTSTR pszKey,double& dVal) const;
BOOL GetAt(LPCTSTR pszKey,AcGeDoubleArray& arVal) const;
BOOL GetAt(LPCTSTR pszKey,AcGeVector3d& vt) const;
BOOL GetAt(LPCTSTR pszKey,AcGePoint3d& ptGe) const;
BOOL GetAt(LPCTSTR pszKey,AcGePoint3dArray& arPt) const;
BOOL GetAt(LPCTSTR pszKey,AcGeMatrix3d& xform) const;
BOOL GetAt(LPCTSTR pszKey,CString &sValue) const;
/*
TCHAR [] 作为参数时,会退化为 TCHAR*。
所以, 程序中 GetAt(LPCTSTR, TCHAR[]) 的情况下,会调用此重载。
而数组退化后的指针无法使用strlen()得到 pszValue的真实长度。
内部的 strcpy() 会导致缓冲区溢出,而strcpy_s/strncpy_s 得不到长度参数,也无法使用,故废弃。
字符数组的情况,会用 下面的 GetAt(LPCTSTR pszKey, TCHAR(&va)[N]) 模板来处理。
字符串缓存的情况,会用 GetAt(LPCTSTR pszKey, TCHAR* psz, const int &len) 处理。
*/
//BOOL GetAt(LPCTSTR pszKey,TCHAR* pszValue) const;
BOOL GetAt(LPCTSTR pszKey,AcDbObjectId& id) const;
BOOL GetAt(LPCTSTR pszKey,AcDbHandle& handle,AcDbDatabase* pDb = NULL) const;
BOOL SetAt(LPCTSTR pszKey,int iIndex,LPCTSTR pszValue);
BOOL GetAt(LPCTSTR pszKey,int iIndex,CString &sValue) const;
BOOL SetAt(LPCTSTR pszKey,int iIndex,const AecDbObjXDataMap& xDataMap);
BOOL GetAt(LPCTSTR pszKey,int iIndex,AecDbObjXDataMap& xDataMap) const;
BOOL SetAt(LPCTSTR pszKey,const AecXData& XData);
BOOL GetAt(LPCTSTR pszKey,AecXData& XData) const;
BOOL GetAt(LPCTSTR pszKey, TCHAR* psz, const int &len) const;
BOOL HasKey(LPCTSTR pszKey,int& nVt) const;
void Empty();
BOOL RemoveAt(LPCTSTR pszKey);
BOOL RemoveAt(LPCTSTR pszKey,int nIndex);
//支持扩展数据的4个方法 bXRecord = fase 操作扩展数据 bXRecord = true 操作扩展词典
BOOL Write(AcDbObject* pEnt,LPCTSTR pszApp,BOOL bXRecord = FALSE,BOOL bAppend = FALSE,BOOL bOnlyWriteSecond = FALSE) const;
BOOL Write(const AcDbObjectId& id,LPCTSTR pszApp,BOOL bXRecord = FALSE,BOOL bAppend = FALSE,BOOL bOnlyWriteSecond = FALSE) const;
BOOL Write(CFile* pFileOut,BOOL bWriteUserData) const;
BOOL Write(CString &strOut, BOOL bWriteUserData) const;
BOOL WriteExDic(AcDbObject* pEnt,LPCTSTR pszApp) const;
BOOL WriteExDic(const AcDbObjectId& id,LPCTSTR pszApp) const;
BOOL ReadExDic(AcDbObject* pEnt,LPCTSTR pszApp);
BOOL ReadExDic(const AcDbObjectId& id,LPCTSTR pszApp);
BOOL Read(AcDbObject* pEnt,LPCTSTR pszApp,BOOL bXRecord = FALSE,BOOL bKeyAsSecond = FALSE);
BOOL Read(const AcDbObjectId& id,LPCTSTR pszApp,BOOL bXRecord = FALSE,BOOL bKeyAsSecond = FALSE);
BOOL Read(CFile* pFileIn,BOOL bWriteUserData);
BOOL Read(LPCTSTR pszIn, BOOL bWriteUserData);
AecDbObjXDataMap& operator = (const AecDbObjXDataMap& srcMap);
BOOL CopyFrom(const AecDbObjXDataMap* pSrc);
BOOL AppendFrom(const AecDbObjXDataMap* pSrc);
virtual Acad::ErrorStatus dxfOutFields(AcDbDxfFiler* pFiler) const;
virtual Acad::ErrorStatus dxfInFields(AcDbDxfFiler* pFiler);
virtual Acad::ErrorStatus dwgOutFields(AcDbDwgFiler* pFiler) const;
virtual Acad::ErrorStatus dwgInFields(AcDbDwgFiler* pFiler);
typedef std::map<CString,AecXData>::iterator It;
typedef std::map<CString,AecXData>::const_iterator CIt;
size_t Count() const;
It Begin();
BOOL GetNext(It& it,CString& sKey,AecXData& xData);
It End();
//prinf输出
void List() const;
// 输出到字符串数组:每个元素占两项(先 key,后 value),供界面按两列展示。
void List(std::vector<CString> &pList) const;
int ComparedTo(const AecDbObjXDataMap* pXDataMap) const;
// 增加 clone 的 xdatamap 的关系复制维护
void BeginCloneXlation(AecDbObjXDataMap* pMapClone,AcDbIdMapping& idMap) const;
template <int N>
BOOL GetAt(LPCTSTR pszKey, TCHAR(&va)[N]) const
{
CString s;
if (GetAt(pszKey, s) == FALSE) return FALSE;
// 虽然传入是的数组,最后一个字符可以不是'\0'。
// 但是,外部对字符数组的使用,大部分是按照字符串指针来使用的。
// 所以,为了外部使用的安全,还是让数组的最后一位是'\0'。
_tcsncpy_s(va, N, s, N - 1);
return TRUE;
}
public:
BOOL XDMap2Resbuf(LPCTSTR pszApp,struct resbuf*& pRb,BOOL bXRecord = FALSE,BOOL bOnlyWriteSecond = FALSE) const;
BOOL Resbuf2XDMap(struct resbuf* pRb,BOOL bXRecord = FALSE,AcDbDatabase* pDb = NULL,BOOL bKeyAsSecond = FALSE );
SHJson::WValue& ToJson() const;
bool ByJson(const SHJson::WValue &v);
static bool getBimDatas(const AecDbObjXDataMap &XData, SH_BIM_BLOCK &bim);
static bool setBimDatas(AecDbObjXDataMap &XData, const SH_BIM_BLOCK &bim);
static bool findBimData(const AecDbObjXDataMap &XData
, LPCTSTR pszKey
, CString &strValue
, CString &strUserKey );
static bool getBimData(const AecDbObjXDataMap &XData, LPCTSTR pszKey, CString &strValue);
static bool setBimData(AecDbObjXDataMap &XData, LPCTSTR pszKey, LPCTSTR pszValue);
static bool delBimData(AecDbObjXDataMap &XData, LPCTSTR pszKey);
private:
BOOL ParseToRecords(CString& sText,CStringArray& arRecords) const;
BOOL ExtractRecord(CString& sRecord,CString& sKey,CString& sType,CString& sInfo) const;
BOOL StringToAcGePoint3d(CString& sText,AcGePoint3d& ptGe) const;
BOOL StringToAcGeVector3d(CString& sText,AcGeVector3d& ptGe) const;
void SecondAsKey(CString& sTemp,AecXData& xData);
// 把 xdata 以 pszKey 存入(已存在则覆盖)。接管 xdata 的所有权(内部把源置空)。
void SetXData(LPCTSTR pszKey, AecXData &xdata);
private:
mutable SHJson::WValue m_json;//临时,不序列化
std::map<CString,AecXData> m_xData;//序列化
};
#endif //_AecDbObjXDataMap_H__