xmlconfig.cpp
来自「symbian 下的helix player源代码」· C++ 代码 · 共 2,482 行 · 第 1/4 页
CPP
2,482 行
}
return CfgVarString;
}
void
XMLConfig::StuffRegistry(XMLConfigList* list)
{
CHXSimpleList::Iterator i;
char* regname = list->m_parentnode->get_registry_name();
if(m_pRegistry->GetTypeByName(regname) == PT_UNKNOWN)
{
m_pRegistry->AddComp(regname);
}
delete [] regname;
for(i = list->Begin(); i != list->End(); ++i)
{
XMLConfigListNode* node = (XMLConfigListNode*)(*i);
switch(node->m_type)
{
case CfgVar:
regname = node->get_registry_name();
switch(GetVarType(node))
{
case CfgVarInt:
// printf("%s = %ld\n", regname, node->m_int);
if(m_pRegistry->GetTypeByName(regname) == PT_UNKNOWN)
{
m_pRegistry->AddInt(regname, node->m_int);
}
else
{
m_pRegistry->SetIntByName(regname, node->m_int);
}
break;
case CfgVarString:
{
CHXBuffer* pBuffer = new CHXBuffer;
pBuffer->AddRef();
pBuffer->Set((UINT8*)node->m_value,
strlen(node->m_value) + 1);
// printf("%s = %s\n", regname, (const char *)pBuffer->GetBuffer());
if(m_pRegistry->GetTypeByName(regname) == PT_UNKNOWN)
{
m_pRegistry->AddStr(regname, pBuffer);
}
else
{
m_pRegistry->SetStrByName(regname, pBuffer);
}
pBuffer->Release();
break;
}
case CfgVarBool:
// printf("%s = %ld\n", regname, node->m_bool);
if(m_pRegistry->GetTypeByName(regname) == PT_UNKNOWN)
{
m_pRegistry->AddInt(regname, node->m_bool);
}
else
{
m_pRegistry->SetIntByName(regname, node->m_bool);
}
break;
}
delete [] regname;
break;
case CfgList:
StuffRegistry(node->m_pList);
break;
}
}
}
//
// Method: Read
//
// Parameters:
//
// filename: The file to be read.
// pWinRegKey: The Windows registry key to be filled in (can be
// NULL if no registry writing is needed).
// pServRegKey: The Server registry key to be filled in.
//
// Notes: the bIncludedFile is for internal recursive use only. Do not
// set it when calling from outside this object.
HX_RESULT
XMLConfig::Read(char* filename,
char* pServRegKey,
BOOL bIncludedFile)
{
HX_RESULT hResult = HXR_OK;
FILE* fp=0;
XMLParser parser;
XMLTag* tag = 0;
CBigByteQueue queue(MAX_TAG_SIZE);
int l=0;
BOOL filedone = FALSE;
UINT32 indent = 0;
HX_ASSERT(filename && strlen(filename));
HX_VECTOR_DELETE(m_filename);
m_filename = new_string(filename);
fp = fopen(filename, "r");
if (!fp)
{
ERRMSG(m_pMessages, "%s: file not found", filename);
return HXR_FILE_NOT_FOUND;
}
if(!m_pList)
{
m_pList = new XMLConfigList;
m_pList->m_parentnode = new XMLConfigListNode;
m_pList->m_parentnode->m_name = new_string(pServRegKey);
m_pList->m_parentnode->m_parent = NULL;
}
// read the config file into the byte queue
INT32 nBufSize = 16384;
BYTE* pBuf = new BYTE[nBufSize];
while (!filedone && hResult == HXR_OK)
{
l = fread(pBuf, 1, nBufSize, fp);
if (l > 0)
{
if (!queue.EnQueue(pBuf, l))
{
if (!queue.Grow(l))
{
ERRMSG(m_pMessages,
"error expanding data structure while parsing %s",
filename);
hResult = HXR_FAIL;
}
if (!queue.EnQueue(pBuf, l))
{
ERRMSG(m_pMessages,
"unknown error while parsing %s",
filename);
hResult = HXR_FAIL;
}
}
}
else
{
filedone = TRUE;
}
}
UINT32 bytesUsed=0;
UINT32 bytesAvail=0;
BYTE* p=0;
while (hResult == HXR_OK && (bytesAvail = queue.GetQueuedItemCount()) > 0)
{
if (bytesAvail > nBufSize)
{
HX_VECTOR_DELETE(pBuf);
pBuf = new BYTE[bytesAvail];
nBufSize = bytesAvail;
}
p = pBuf;
queue.DeQueue(pBuf, bytesAvail);
bytesUsed = bytesAvail;
HX_DELETE(tag);
XMLParseResult res = parser.Parse((const char*&)p, bytesAvail, tag);
queue.EnQueue(p, bytesAvail - (p - pBuf));
switch(res)
{
case XMLPNoClose:
// A tag opener was found, but no closer yet.
if (filedone)
{
pBuf[bytesAvail - 1] = '\0';
if (bytesAvail > MAX_ERROR_CHARS)
{
pBuf[MAX_ERROR_CHARS - 1] = '\0';
}
ERRMSG(m_pMessages,
"%s: Missing close for tag '%s'...", m_filename, pBuf);
hResult = HXR_FAIL;
}
break;
case XMLPNoTagType:
*p = 0;
ERRMSG(m_pMessages,
"%s: Badly formed tag '%s'", m_filename, pBuf);
break;
case XMLPBadAttribute:
*p = 0;
ERRMSG(m_pMessages,
"%s: Badly formed attribute in '%s'", m_filename,
pBuf);
break;
case XMLPPlainText:
//Some text. What do we care?
break;
case XMLPBadEndTag:
*p = 0;
ERRMSG(m_pMessages,
"%s: Unexpected end tag '</%s>'", m_filename, tag->m_name);
hResult = HXR_FAIL;
break;
case XMLPComment:
// A comment, fine.
if(tag != NULL)
{
//Some kind of comment directive
XMLAttribute* pAttr = tag->attribute(0);
if(pAttr &&
pAttr->name)
{
if(strcasecmp(pAttr->name, "include") == 0)
{
char* path;
char* newfile = new char[1024];
if(!strchr(tag->attribute(0)->value,
OS_SEPARATOR_CHAR) &&
((path = strrchr(m_filename, OS_SEPARATOR_CHAR))
!= NULL))
{
path++;
if (path - m_filename < 1024)
{
strncpy(newfile, m_filename, path - m_filename);
newfile[path - m_filename] = '\0';
}
SafeStrCat(newfile, tag->attribute(0)->value, 1024);
}
else
{
SafeStrCpy(newfile, tag->attribute(0)->value, 1024);
}
char* filename = m_filename;
m_filename = NULL;
Read(newfile, pServRegKey, TRUE);
delete[] m_filename;
m_filename = filename;
delete[] newfile;
}
}
}
break;
case XMLPDirective:
// A directive. We don't handle any yet.
break;
case XMLPProcInst:
// A processing Instruction, whee!
break;
case XMLPTag:
{
if(Expand(tag, &queue))
break;
XMLConfigListNode* node = new XMLConfigListNode;
node->m_parent = m_pList->m_parentnode;
node->m_vserver = m_vserver;
if(tag->m_need_close)
{
if(strcasecmp(tag->m_name, "list") == 0)
{
const char* name = tag->get_attribute("name");
if(!name)
{
ERRMSG(m_pMessages,
"%s: List tag requires a name attribute",
m_filename);
// Process anyway, give it a dummy name
name = "XXXBADLIST";
}
node->m_type = CfgList;
node->m_name = new_string(name);
node->m_num = tag->elem;
m_pList->AddTail(node);
m_pListStack.Push(m_pList);
node->m_pList = new XMLConfigList;
m_pList = node->m_pList;
m_pList->m_parentnode = node;
}
else if(strcasecmp(tag->m_name, "server") == 0)
{
const char* server = tag->get_attribute("number");
if(!server)
{
ERRMSG(m_pMessages,
"%s: Server tag requires a number, defaulting to 0",
m_filename);
m_vserver = 0;
}
else
{
char vserver_str[64]; /* Flawfinder: ignore */
m_vserver = atol(server);
sprintf(vserver_str, "server%ld", m_vserver); /* Flawfinder: ignore */
if(m_pRegistry->GetTypeByName(vserver_str) == PT_UNKNOWN)
{
m_pRegistry->AddComp(vserver_str);
sprintf(vserver_str, "server%ld.config", /* Flawfinder: ignore */
m_vserver);
m_pRegistry->AddComp(vserver_str);
}
}
}
}
else if(tag->m_type != XMLEndTag)
{
const char* name = tag->get_attribute("name");
const char* value = tag->get_attribute("value");
if(name && value)
{
node->m_type = CfgVar;
node->m_name = new_string(name);
node->m_value = new_string(value);
node->m_num = tag->elem;
m_pList->AddTail(node);
}
}
else
{
// An End Tag
if(strcasecmp(tag->m_name, "list") == 0)
{
m_pList = (XMLConfigList*)m_pListStack.Pop();
}
else if(strcasecmp(tag->m_name, "server") == 0)
{
if(m_vserver < 0)
{
ERRMSG(m_pMessages,
"%s: </Server> Tag with no matching <Server>",
m_filename);
}
else
{
m_vserver = -1;
}
}
}
break;
}
}
}
if(hResult == HXR_OK && !bIncludedFile)
{
StuffRegistry(m_pList);
delete m_pList->m_parentnode;
}
if (hResult == HXR_OK && !m_pListStack.IsEmpty())
{
ERRMSG(m_pMessages,
"%s: <List> tag with no matching </List>",
m_filename);
hResult = HXR_FAIL;
}
// cleanup
if (fp) fclose(fp);
HX_VECTOR_DELETE(pBuf);
HX_DELETE(tag);
return hResult;
}
char*
XMLConfig::XMLConfigListNode::get_registry_name(INT32 vserver)
{
char* name;
if(m_parent)
{
char* parentname = m_parent->get_registry_name(
vserver < 0 ? m_vserver : vserver);
name = new char[strlen(parentname) + strlen(m_name) + 2];
sprintf(name, "%s.%s", parentname, m_name); /* Flawfinder: ignore */
delete [] parentname;
return name;
}
else
{
if(vserver >= 0)
{
name = new char[26 + strlen(m_name) + 2];
sprintf(name, "server%ld.%s", vserver, m_name); /* Flawfinder: ignore */
}
else
{
name = new_string(m_name);
}
return name;
}
}
///XXXPM This func does not correctly handle the original file not
///being there.
HX_RESULT
XMLConfig::WriteToFile(const char* pKeyName, const char* pFileName)
{
UINT32 ulListsToIgnore = 0;
/*
* Make sure we have a valid file name to use.
*/
if (!pFileName)
{
return HXR_FAIL;
}
/*
* Copy filename to filename.bak.
*/
char *pNewFileName = new char[strlen(pFileName) + strlen(".bak") + 1];
sprintf(pNewFileName, "%s.bak", pFileName); /* Flawfinder: ignore */
FILE* fpOld = fopen(pFileName, "r");
FILE* fpNew = fopen(pNewFileName, "w");
if (!fpNew || !fpOld)
{
HX_VECTOR_DELETE(pNewFileName);
if (fpNew) fclose(fpNew);
if (fpOld) fclose(fpOld);
return HXR_FAIL;
}
INT32 nBufSize=16384;
BYTE* pBuf = new BYTE[nBufSize];
int iGot = 0;
while (!feof(fpOld))
{
iGot = fread(pBuf, sizeof(char), nBufSize, fpOld);
if (iGot)
{
fwrite(pBuf, sizeof(char), iGot, fpNew);
}
}
fclose(fpNew);
fclose(fpOld);
#ifdef _UNIX
chmod(pNewFileName, 0700);
#endif //UNIX
fpNew = fopen(pFileName, "w");
fpOld = fopen(pNewFileName, "r");
HX_VECTOR_DELETE(pNewFileName);
if (!fpNew || !fpOld)
{
if (fpNew) fclose(fpNew);
if (fpOld) fclose(fpOld);
return HXR_FAIL;
}
int l;
BOOL filedone = 0;
XMLTag* tag = 0;
XMLTag* wspacetag = 0;
CBigByteQueue queue(MAX_TAG_SIZE);
XMLParser parser;
HX_RESULT hResult = HXR_OK;
/*
* Files are all aready. Now we need to build our config levels list.
*/
CHXSimpleList levlist;
/*
* Add for level 0.
*/
CHXSimpleList* pNewList = new CHXSimpleList;
IHXValues* pValues = 0;
_AddPropsToList(pNewList, pKeyName, m_pRegistry);
XMLConfigString curr_level;
curr_level.AddLevel(pKeyName);
while (!filedone && hResult == HXR_OK)
{
l = fread(pBuf, 1, nBufSize, fpOld);
if (l > 0)
{
if (!queue.EnQueue(pBuf, l))
{
if (!queue.Grow(l))
{
ERRMSG(m_pMessages,
"error expanding data structure while parsing");
hResult = HXR_FAIL;
}
if (!queue.EnQueue(pBuf, l))
{
ERRMSG(m_pMessages,
"unknown error while parsing");
hResult = HXR_FAIL;
}
}
}
else
{
filedone = TRUE;
}
}
UINT32 bytesUsed=0;
UINT32 bytesAvail=0;
BYTE* p=0;
while (hResult == HXR_OK && (bytesAvail = queue.GetQueuedItemCount()) > 0)
{
if (bytesAvail > nBufSize)
{
HX_VECTOR_DELETE(pBuf);
pBuf = new BYTE[bytesAvail];
nBufSize = bytesAvail;
}
p = pBuf;
queue.DeQueue(pBuf, bytesAvail);
bytesUsed = bytesAvail;
HX_DELETE(tag);
XMLParseResult res = parser.Parse((const char*&)p, bytesAvail, tag);
queue.EnQueue(p, bytesAvail - (p - pBuf));
switch(res)
{
case XMLPNoClose:
// A tag opener was found, but no closer yet.
if (filedone)
{
pBuf[bytesAvail - 1] = '\0';
if (bytesAvail > MAX_ERROR_CHARS)
{
pBuf[MAX_ERROR_CHARS - 1] = '\0';
}
ERRMSG(m_pMessages,
"%s: Missing close for tag %s...", m_filename, pBuf);
hResult = HXR_FAIL;
}
break;
case XMLPNoTagType:
*p = 0;
ERRMSG(m_pMessages,
"%s: Badly formed tag %s", m_filename, pBuf);
break;
case XMLPBadAttribute:
*p = 0;
ERRMSG(m_pMessages,
"%s: Badly formed attribute in %s", m_filename,
pBuf);
break;
case XMLPPlainText:
/*
* Just plaintext. Dump this out directly.
*/
if (wspacetag)
{
delete wspacetag;
}
wspacetag = tag;
tag = 0;
/*
fwrite(tag->m_cur_attribute->value, sizeof(char),
strlen(tag->m_cur_attribute->value), fpNew);
*/
break;
case XMLPBadEndTag:
*p = 0;
ERRMSG(m_pMessages,
"%s: Unexpected tag %s", m_filename, pBuf);
break;
case XMLPComment:
/*
* Just a comment. Dump it out. Comment lives from
* p to pBuf.
*/
if (wspacetag)
{
fwrite(wspacetag->m_cur_attribute->value, sizeof(char),
strlen(wspacetag->m_cur_attribute->value), fpNew);
delete wspacetag;
wspacetag = 0;
}
fwrite(pBuf, sizeof(char), p - pBuf, fpNew);
break;
case XMLPDirective:
// A directive. We don't handle any yet.
break;
case XMLPProcInst:
/*
* Just dump processing instructions as we read them.
*/
if (wspacetag)
{
fwrite(wspacetag->m_cur_attribute->value, sizeof(char),
strlen(wspacetag->m_cur_attribute->value), fpNew);
delete wspacetag;
wspacetag = 0;
}
fwrite(pBuf, sizeof(char), p - pBuf, fpNew);
break;
case XMLPTag:
{
if(Expand(tag, &queue))
break;
if(tag->m_need_close)
{
if(strcasecmp(tag->m_name, "list") == 0)
{
if (ulListsToIgnore)
{
ulListsToIgnore++;
}
else
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?