📄 xml.cpp
字号:
#include "stdafx.h"
#include "xml.h"
//#include "./export/misc.h"
//#include "./export/md5.h"
//#include "./export/blowfish.h"
#include <io.h>
#include <stdio.h>
#include <stdarg.h>
#include <malloc.h>
CXML::CXML()
: m_heapXmlNodes(1,128,sizeof(XMLNODE),TRUE)
, m_heapXmlAttribs(1,128,sizeof(XMLATTRIB),TRUE)
, m_heapXmlSmallStrs(1,128,sizeof(XMLSMALLSTR),TRUE)
, m_pNodeLinks(NULL)
, m_pNodeLinkLast(NULL)
, m_pAttribLinks(NULL)
, m_pAttribLinkLast(NULL)
{
}
CXML::~CXML()
{
// 检查并释放当前XML文件
FreeXml();
}
BOOL CXML::LoadXml(const char* lpszXmlFile)
{
// 打开XML文件并进行读取
FILE* fpXml=fopen(lpszXmlFile,"rb");
if(fpXml==NULL) return FALSE;
long nXmlLen=filelength(fileno(fpXml));
if(nXmlLen<0)
{ fclose(fpXml);
return FALSE;
}
char* lpszXmls=(char*)malloc(nXmlLen+1);
if(lpszXmls==NULL)
{ fclose(fpXml);
return FALSE;
}
memset(lpszXmls,0,nXmlLen+1);
nXmlLen=fread(lpszXmls,1,nXmlLen,fpXml);
fclose(fpXml);
// 从缓冲区装载XML
BOOL bLoadSuccess=LoadXml(lpszXmls,nXmlLen);
if(lpszXmls!=NULL) free(lpszXmls);
return bLoadSuccess;
}
BOOL CXML::SaveXml(const char* lpszXmlFile)
{
// 打开XML文件并进行写入
FILE* fpXml=fopen(lpszXmlFile,"wb");
if(fpXml==NULL) return FALSE;
// 从第一个子节点开始写入
LPXMLNODE pChildNode=m_pNodeLinks;
while(pChildNode!=NULL)
{ SaveXmlNodeAndChilds(pChildNode,fpXml,0);
pChildNode=(LPXMLNODE)pChildNode->m_pNext;
}
// 关闭XML文件
fclose(fpXml);
return TRUE;
}
BOOL CXML::SaveXml(char* lpszXmlBuf,LONG nXmlBufLen,LONG* pnUsedOrNeeded)
{
// 检查默认输出,后面的参数可以为空,清除返回
LONG nUsedOrNeeded=0;
if(pnUsedOrNeeded==NULL) pnUsedOrNeeded=&nUsedOrNeeded;
(*pnUsedOrNeeded)=0;
// 从第一个子节点开始写入
LPXMLNODE pChildNode=m_pNodeLinks;
while(pChildNode!=NULL)
{ SaveXmlNodeAndChilds(pChildNode,lpszXmlBuf,nXmlBufLen,pnUsedOrNeeded,0);
pChildNode=(LPXMLNODE)pChildNode->m_pNext;
}
// 检查是否写完,还是只写了部分
if((*pnUsedOrNeeded)>=nXmlBufLen)
{ // 为已经写入的部分加入'\0'
if(nXmlBufLen>0) lpszXmlBuf[nXmlBufLen-1]='\0';
// 需要加上'\0'的长度
(*pnUsedOrNeeded)++;
// 返回失败
return FALSE;
}
// 全部写入完成,为已经写入的部分加入'\0',并将实际使用长度加上补充的长度
lpszXmlBuf[(*pnUsedOrNeeded)]='\0';
(*pnUsedOrNeeded)++;
return TRUE;
}
BOOL CXML::LoadXml(const char* lpszXml,LONG nXmlLen)
{
// 检查参数
if(lpszXml==NULL&&nXmlLen<=0) return FALSE;
// 检查并释放当前XML文件
FreeXml();
// 从缓冲区加载XML,这里将执行预处理,去掉其中的回车换行
char* lpszXmlTemps=TMALLOC(nXmlLen+1,char);
memset(lpszXmlTemps,0,nXmlLen+1);
memcpy(lpszXmlTemps,lpszXml,nXmlLen);
// 分析XML格式
if(!ParsingXml(lpszXmlTemps,nXmlLen))
{ TFREE(lpszXmlTemps);
FreeXml();
return FALSE;
}
TFREE(lpszXmlTemps);
return TRUE;
}
VOID CXML::FreeXml()
{
// 释放节点
LPXMLNODE pNodeLink=m_pNodeLinks;
while(pNodeLink!=NULL)
{ LPXMLNODE pNodeTemp=(LPXMLNODE)pNodeLink;
pNodeLink=(LPXMLNODE)pNodeLink->m_pHeapLink;
FreeXmlNode(pNodeTemp);
}
m_pNodeLinks=NULL;
m_pNodeLinkLast=NULL;
// 释放属性节点
LPXMLATTRIB pAttribLink=m_pAttribLinks;
while(pAttribLink!=NULL)
{ LPXMLATTRIB pAttribTemp=(LPXMLATTRIB)pAttribLink;
pAttribLink=(LPXMLATTRIB)pAttribLink->m_pHeapLink;
FreeXmlAttrib(pAttribTemp);
}
m_pAttribLinks=NULL;
m_pAttribLinkLast=NULL;
}
// 配置读取
INT CXML::GetXmlProfileInt(LPCSTR lpszKeyPath,INT nDefault)
{ LPCSTR pszValue=GetXmlValueWithPath(lpszKeyPath);
if(pszValue!=NULL) return atol(pszValue);
return nDefault;
}
DWORD CXML::GetXmlProfileString(LPCSTR lpszKeyPath,LPCSTR lpDefault,LPSTR lpReturnedString,DWORD nSize)
{ // 如果返回串地址空
if(lpReturnedString==NULL) return 0;
// 填写正确的返回内容
LPCSTR pszValue=GetXmlValueWithPath(lpszKeyPath);
if(pszValue!=NULL)
{ nstrcpy(lpReturnedString,pszValue,nSize);
return strlen(lpReturnedString);
}
// 填写默认的返回内容
nstrcpy(lpReturnedString,lpDefault,nSize);
return strlen(lpReturnedString);
}
LPCSTR CXML::GetXmlProfileString(LPCSTR lpszKeyPath,LPCSTR lpDefault)
{ LPCSTR pszValue=GetXmlValueWithPath(lpszKeyPath);
if(pszValue!=NULL) return pszValue;
return lpDefault;
}
LPCSTR CXML::GetXmlProfileSafeString(LPCSTR lpszKeyPath,LPCSTR lpDefault)
{ LPCSTR pszValue=GetXmlValueWithPath(lpszKeyPath);
if(pszValue!=NULL) return pszValue;
if(lpDefault!=NULL) return lpDefault;
return "";
}
// 配置写入
BOOL CXML::SetXmlProfileInt(LPCSTR lpszKeyPath,INT nValue)
{ CHAR szBuffer[MAX_PATH]={0};
nsprintf(szBuffer,sizeof(szBuffer),"%d",nValue);
return SetXmlValueWithPath(lpszKeyPath,szBuffer);
}
BOOL CXML::SetXmlProfileString(LPCSTR lpszKeyPath,LPCSTR pszValue)
{ return SetXmlValueWithPath(lpszKeyPath,pszValue);
}
// 路径创建
LPXMLNODE CXML::CreateXmlWithPath(const char* lpszXmlPath,DWORD dwFlag)
{ return FindXmlWithPath(lpszXmlPath,TRUE,dwFlag);
}
BOOL CXML::SetXmlValueWithPath(const char* lpszXmlPath,const char* lpszValue)
{ LPXMLNODE pNode=CreateXmlWithPath(lpszXmlPath,XMLNODE_KEYSET);
if(pNode==NULL) return FALSE;
return SetXmlNodeValue(pNode,lpszValue);
}
BOOL CXML::SetXmlAttribValueWithPath(const char* lpszXmlPath,const char* pszName,const char* lpszValue)
{ LPXMLNODE pNode=FindXmlWithPath(lpszXmlPath);
if(pNode==NULL) return FALSE;
return SetXmlAttribValue(pNode,pszName,lpszValue);
}
// 路径查找
LPXMLNODE CXML::FindXmlWithPath(const char* lpszXmlPath,BOOL bCreate,DWORD dwFlag)
{
// 判断并复制出路径
if(lpszXmlPath==NULL) return NULL;
char* pszTemp=(char*)alloca(strlen(lpszXmlPath)+1);
strcpy(pszTemp,lpszXmlPath);
// 查找路径,例如/root/version/或者root/version
LPXMLNODE pParentNode=NULL;
BOOL bParentIsCreated=FALSE;
for(;;)
{ // 得到关键字的头部
while((*pszTemp)=='/'||(*pszTemp)==' '||(*pszTemp)=='\t') pszTemp++;
if((*pszTemp)=='\0') break;
char* pszKey=pszTemp;
// 得到关键字的尾部
while((*pszTemp)!='\0'&&(*pszTemp)!='/') pszTemp++;
char* pszKeyEnd=pszTemp;
if((*pszTemp)!='\0') pszTemp++;
// 截取字段并进行查找
pszKeyEnd--;
while((*pszKeyEnd)==' '||(*pszKeyEnd)=='\t') pszKeyEnd--;
pszKeyEnd++;
(*pszKeyEnd)='\0';
LPXMLNODE pXmlNode=FindXmlNode(pParentNode,pszKey);
if(pXmlNode==NULL)
{ if(!bCreate) return NULL;
// 如果不是创建的第一个节点,那么修正刚才创建的节点类型
if(bParentIsCreated) pParentNode->m_dwFlag=XMLNODE_KEYSET;
bParentIsCreated=TRUE;
// 判断父类型是否能够创建子类型
if(pParentNode!=NULL&&pParentNode->m_dwFlag!=XMLNODE_KEYSET) return NULL;
// 创建当前类型的节点
pXmlNode=AllocXmlNodeAtTail(pParentNode);
pXmlNode->m_Key=AllocXmlStr(pszKey,strlen(pszKey));
pXmlNode->m_dwFlag=dwFlag;
}
pParentNode=pXmlNode;
}
return pParentNode;
}
const char* CXML::GetXmlValueWithPath(const char* lpszXmlPath)
{ LPXMLNODE pNode=FindXmlWithPath(lpszXmlPath);
if(pNode==NULL) return NULL;
return GetXmlNodeValue(pNode);
}
const char* CXML::GetXmlAttribValueWithPath(const char* lpszXmlPath,const char* pszName)
{ LPXMLNODE pNode=FindXmlWithPath(lpszXmlPath);
if(pNode==NULL) return NULL;
return GetXmlAttribValue(pNode,pszName);
}
const char* CXML::GetXmlNodeValue(LPXMLNODE pNode)
{ if(pNode==NULL) return NULL;
LPXMLNODE pChild=(LPXMLNODE)pNode->m_pChild;
if(pChild==NULL||pChild->m_dwFlag!=XMLNODE_VALUE) return NULL;
return pChild->m_Key.m_pStr;
}
LPXMLNODE CXML::FindXmlNode(LPXMLNODE pParent,const char* pszKey)
{
LPXMLNODE pNode=GetFirstChildXmlNode(pParent);
while(pNode!=NULL)
{ if(stricmp(pNode->m_Key.m_pStr,pszKey)==0)
return pNode;
pNode=GetNextXmlNode(pNode);
}
return NULL;
}
LPXMLNODE CXML::GetFirstChildXmlNode(LPXMLNODE pParent)
{
// 如果父节点为空,表明取根节点的子节点,按照分配的逻辑应该是链表的第一个
if(pParent==NULL) return m_pNodeLinks;
// 否则返回指定节点的第一个节点
return (LPXMLNODE)pParent->m_pChild;
}
LPXMLNODE CXML::GetNextXmlNode(LPXMLNODE pNode)
{ if(pNode==NULL) return NULL;
return (LPXMLNODE)pNode->m_pNext;
}
BOOL CXML::SetXmlNodeValue(LPXMLNODE pNode,const char* pszValue)
{ // 检查参数是否合法
if(pNode==NULL||pszValue==NULL) return FALSE;
// 得到或创建子节点
LPXMLNODE pChild=(LPXMLNODE)pNode->m_pChild;
if(pChild==NULL)
{ pChild=AllocXmlNodeAtTail(pNode);
pChild->m_dwFlag=XMLNODE_VALUE;
}
// 判断子节点类型
if(pChild->m_dwFlag!=XMLNODE_VALUE) return FALSE;
// 更新子节点数据
FreeXmlStr(pChild->m_Key);
pChild->m_Key=AllocXmlStr(pszValue,strlen(pszValue));
return TRUE;
}
// 通过名称获取属性值
const char* CXML::GetXmlAttribValue(LPXMLNODE pNode,const char* pszName)
{ LPXMLATTRIB pAttrib=FindXmlAttrib(pNode,pszName);
if(pAttrib==NULL) return NULL;
return pAttrib->m_Value.m_pStr;
}
// 通过名称查找属性
LPXMLATTRIB CXML::FindXmlAttrib(LPXMLNODE pNode,const char* pszName)
{ LPXMLATTRIB pAttrib=GetFirstXmlAttrib(pNode);
while(pAttrib!=NULL)
{ if(stricmp(pAttrib->m_Name.m_pStr,pszName)==0)
return pAttrib;
pAttrib=GetNextXmlAttrib(pAttrib);
}
return NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -