Ai
6 Star 16 Fork 9

莫钧/SignalSim

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
XmlElement.cpp 11.48 KB
一键复制 编辑 原始数据 按行查看 历史
Jun Mo 提交于 2020-07-14 07:08 +08:00 . initial version
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
//----------------------------------------------------------------------
// XmlElement.cpp:
// Definition of XML file operation class
//
// Copyright (C) 2020-2029 by Jun Mo, All rights reserved.
//
//----------------------------------------------------------------------
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include "XmlElement.h"
CSimpleDict::CSimpleDict()
{
DictItemNumber = 0;
Dictionary = (DictItem *)malloc(sizeof(DictItem) * DICT_ITEM_INC);
DictArraySize = DICT_ITEM_INC;
}
CSimpleDict::~CSimpleDict()
{
free(Dictionary);
}
CSimpleDict& CSimpleDict::operator=(const CSimpleDict& dict)
{
if (DictArraySize != dict.DictArraySize)
{
DictArraySize = dict.DictArraySize;
DictItemNumber = dict.DictItemNumber;
Dictionary = (DictItem *)realloc(Dictionary, sizeof(DictItem) * DictArraySize);
}
memcpy(Dictionary, dict.Dictionary, sizeof(DictItem) * DictItemNumber);
return *this;
}
bool CSimpleDict::Add(char *key, char *value)
{
DictItem *NewDict;
if (strlen(key) > MAX_KEY_LENGTH || strlen(value) > MAX_VALUE_LENGTH)
return false;
if (DictItemNumber == DictArraySize)
{
DictArraySize += DICT_ITEM_INC;
NewDict = (DictItem *)realloc(Dictionary, sizeof(DictItem) * DictArraySize);
if (NewDict == NULL)
return false;
Dictionary = NewDict;
}
strcpy(Dictionary[DictItemNumber].key, key);
strcpy(Dictionary[DictItemNumber].value, value);
DictItemNumber ++;
return true;
}
bool CSimpleDict::Delete(char *key)
{
int index;
index = Find(key);
if (index < 0)
return false;
if (index != (DictItemNumber - 1))
memmove(Dictionary + index, Dictionary + index + 1, sizeof(DictItem) * (DictItemNumber - index - 1));
DictItemNumber --;
return true;
}
int CSimpleDict::Find(char *key)
{
int i;
for (i = 0; i < DictItemNumber; i ++)
if (strcmp(Dictionary[i].key, key) == 0)
break;
return (i == DictItemNumber) ? -1 : i;
}
CXmlElement::CXmlElement()
{
tag[0] = 0;
text[0] = 0;
iChildNumber = 0;
ChildElements = SiblingElements = NULL;
Completed = true;
}
CXmlElement::CXmlElement(CXmlElement &element)
{
strcpy(this->tag, element.tag);
strcpy(this->text, element.text);
this->Attributes = element.Attributes;
iChildNumber = 0;
ChildElements = SiblingElements = NULL;
Completed = true;
}
CXmlElement::CXmlElement(char *tag, char *text)
{
strcpy(this->tag, tag);
strcpy(this->text, text);
iChildNumber = 0;
ChildElements = SiblingElements = NULL;
Completed = true;
}
CXmlElement::~CXmlElement()
{
DeleteTree();
}
bool CXmlElement::DeleteTree()
{
if (ChildElements)
{
ChildElements->DeleteTree();
delete ChildElements;
ChildElements = NULL;
}
if (SiblingElements)
{
SiblingElements->DeleteTree();
delete SiblingElements;
SiblingElements = NULL;
}
return true;
}
bool CXmlElement::RemoveElement(int index)
{
CXmlElement *PrevElement = NULL, *CurElement = NULL;
if (index < 0)
return false;
if (index == 0)
{
PrevElement = NULL;
CurElement = ChildElements;
}
else
{
PrevElement = GetElement(index-1);
CurElement = PrevElement->SiblingElements;
}
if (!CurElement)
return false;
// remove current element from link list
if (PrevElement)
PrevElement->SiblingElements = CurElement->SiblingElements;
else
ChildElements = CurElement->SiblingElements;
// delete current element
CurElement->DeleteTree();
delete CurElement;
return true;
}
CXmlElement * CXmlElement::GetElement(int index)
{
CXmlElement *Element = ChildElements;
while (Element && index > 0)
{
Element = Element->SiblingElements;
index --;
}
return Element;
}
bool CXmlElement::parse_string(char *string, bool with_tag)
{
char *str = string;
char *p;
CXmlElement *SubElement;
// trim empty characters
while (*str && (*str == ' ' || *str == '\t'))
str ++;
// for string passed in with tag of current element, first extract tag
if (with_tag)
str = process_tag(str);
if (*str == 0)
return Completed;
if (!Completed) // find text
{
// trim empty characters
while (*str && (*str == ' ' || *str == '\t'))
str ++;
// whether followed with '<'
if ((p = strchr(str, '<')) != NULL)
*p = 0;
if (*str && (p ? (p > str) : true))
strcpy(text, str);
// put str to end of text
if (p)
{
*p = '<'; // restore '<'
str = p;
}
else
*str = 0;
}
if (*str != '<')
return Completed;
if (Completed) // for completed element, drop any following character
return true;
p = strchr(str, '>');
if (!p)
return Completed;
// whether this is end of element
if (str[1] == '/')
{
*p = 0;
if (strcmp(tag, str + 2) == 0)
{
Completed = true;
return true;
}
// not end of current element, restore '>'
*p = '>';
// pass to active sub-element
SubElement = GetElement(iChildNumber - 1);
if (SubElement && !(SubElement->Completed))
SubElement->parse_string(str, false);
}
else // this is a new tag
{
// create a new sub-element
if (iChildNumber > 0)
{
SubElement = GetElement(iChildNumber - 1);
if (SubElement->Completed)
{
SubElement->SiblingElements = new CXmlElement;
SubElement = SubElement->SiblingElements;
iChildNumber ++;
}
}
else
{
ChildElements = new CXmlElement;
SubElement = ChildElements;
iChildNumber ++;
}
SubElement->parse_string(str, SubElement->Completed);
}
return Completed;
}
char *CXmlElement::process_tag(char *string)
{
char *left, *right;
char *p;
left = strchr(string, '<');
right = strchr(string, '>');
if (left[1] == '/')
return NULL;
p = left + 1;
while (*p != ' ' && *p != '\t' && *p != '>')
p ++;
*p = 0;
strcpy(tag, left + 1);
p ++;
while (*p && *p != '>')
{
// trim empty characters
while (*p && (*p == ' ' || *p == '\t'))
p ++;
if ((left = strchr(p, '=')) == NULL) // do not find '='
break;
*left = 0;
left ++;
// find contents with in ""
left = strchr(left, '"');
if (!left)
break;
left ++;
right = strchr(left, '"');
if (!right)
break;
*right = 0;
Attributes.Add(p, left);
p = right + 1;
}
if (*p == '/' && p[1] == '>')
{
p ++;
Completed = true;
}
else
Completed = false;
return (*p == '>') ? p + 1 : p;
}
bool CXmlElement::output(FILE *fp, int indent)
{
CXmlElement *Elements;
int i;
// no text and no sub-element
if (strlen(text) == 0 && iChildNumber == 0)
{
for (i = 0; i < indent; i ++)
fprintf(fp, " ");
fprintf(fp, "<%s", tag);
for (i = 0; i < Attributes.DictItemNumber; i ++)
fprintf(fp, " %s=\"%s\"", Attributes.Dictionary[i].key, Attributes.Dictionary[i].value);
fprintf(fp, "/>\n");
return true;
}
// no sub-element
else if (iChildNumber == 0)
{
for (i = 0; i < indent; i ++)
fprintf(fp, " ");
fprintf(fp, "<%s", tag);
for (i = 0; i < Attributes.DictItemNumber; i ++)
fprintf(fp, " %s=\"%s\"", Attributes.Dictionary[i].key, Attributes.Dictionary[i].value);
fprintf(fp, ">");
fprintf(fp, "%s", text);
fprintf(fp, "</%s>\n", tag);
return true;
}
else
{
for (i = 0; i < indent; i ++)
fprintf(fp, " ");
fprintf(fp, "<%s", tag);
for (i = 0; i < Attributes.DictItemNumber; i ++)
fprintf(fp, " %s=\"%s\"", Attributes.Dictionary[i].key, Attributes.Dictionary[i].value);
fprintf(fp, ">\n");
if (strlen(text) > 0)
fprintf(fp, "%s\n", text);
Elements = ChildElements;
while (Elements)
{
Elements->output(fp, indent + 1);
Elements = Elements->SiblingElements;
}
for (i = 0; i < indent; i ++)
fprintf(fp, " ");
fprintf(fp, "</%s>\n", tag);
return true;
}
}
bool CXmlElement::AppendElement(CXmlElement element)
{
CXmlElement *NewElement;
if (iChildNumber == 0)
NewElement = ChildElements = new CXmlElement(element);
else
{
NewElement = ChildElements;
while (NewElement->SiblingElements)
NewElement = NewElement->SiblingElements;
NewElement->SiblingElements = new CXmlElement(element);
NewElement = NewElement->SiblingElements;
}
iChildNumber ++;
NewElement->ChildElements = NewElement->SiblingElements = NULL;
NewElement->iChildNumber = 0;
return true;
}
bool CXmlElement::AppendElement(char *tag, char *text)
{
CXmlElement NewElement(tag, text);
return AppendElement(NewElement);
}
bool CXmlElement::InsertElement(int index, CXmlElement element)
{
CXmlElement *CurElement = NULL, *NewElement;
if (index > 0)
CurElement = GetElement(index-1);
else
CurElement = ChildElements;
if (!CurElement && iChildNumber > 0)
return false;
NewElement = new CXmlElement(element);
if (iChildNumber == 0)
ChildElements = NewElement;
else if (index == 0)
{
ChildElements = NewElement;
NewElement->SiblingElements = CurElement;
}
else
{
NewElement->SiblingElements = CurElement->SiblingElements;
CurElement->SiblingElements = NewElement;
}
iChildNumber ++;
return true;
}
bool CXmlElement::SetTag(char *tag)
{
if (strlen(tag) > MAX_TAG_LENGTH)
return false;
strcpy(this->tag, tag);
return true;
}
bool CXmlElement::SetText(char *text)
{
if (strlen(text) > MAX_TEXT_LENGTH)
return false;
strcpy(this->text, text);
return true;
}
CXmlElementTree::CXmlElementTree()
{
root = NULL;
header[0] = 0;
comment[0] = 0;
}
CXmlElementTree::CXmlElementTree(CXmlElement element)
{
root = new CXmlElement;
*root = element;
header[0] = 0;
comment[0] = 0;
}
CXmlElementTree::~CXmlElementTree()
{
ClearTree();
}
void CXmlElementTree::SetRootElement(CXmlElement element)
{
ClearTree();
root = new CXmlElement;
*root = element;
}
void CXmlElementTree::ClearTree()
{
if (root)
{
root->DeleteTree();
delete root;
root = NULL;
}
}
bool CXmlElementTree::parse(char *filename)
{
FILE *fp;
char string[512], *content;
if ((fp = fopen(filename, "r")) == NULL)
return false;
ClearTree();
while (!feof(fp))
{
fgets(string, 511, fp);
content = string + strlen(string) - 1;
while (*content == '\r' || *content == '\n')
*content -- = 0;
if (((content = found_header(string)) != NULL) && strlen(content) <= MAX_HEADER_LENGTH)
strcpy(header, content);
else if (((content = found_comment(string)) != NULL) && strlen(content) <= MAX_COMMENT_LENGTH)
strcpy(comment, content);
else if (root)
root->parse_string(string, false);
else if (found_tag(string))
{
root = new CXmlElement;
root->parse_string(string, true);
}
}
return true;
}
bool CXmlElementTree::write(char *filename)
{
FILE *fp = fopen(filename, "w");
if (!fp)
return false;
if (strlen(header) > 0)
fprintf(fp, "<?xml %s?>\n", header);
if (strlen(comment) > 0)
fprintf(fp, "<!-- %s-->\n", comment);
if (root)
root->output(fp, 0);
fclose(fp);
return true;
}
char *CXmlElementTree::found_header(char *string)
{
char *left, *right;
left = strchr(string, '<');
right = strchr(string, '>');
if (!left || left[1] != '?')
return NULL;
if (right < string || right[-1] != '?')
return NULL;
if (left[2] != 'x' && left[2] != 'X')
return NULL;
if (left[3] != 'm' && left[3] != 'M')
return NULL;
if (left[4] != 'l' && left[4] != 'L')
return NULL;
// trim off end
right[-1] = 0;
left += 5;
// trim empty characters
while (*left && (*left == ' ' || *left == '\t'))
left ++;
return left;
}
char *CXmlElementTree::found_comment(char *string)
{
char *left, *right;
left = strchr(string, '<');
right = strchr(string, '>');
if (!left || left[1] != '!')
return NULL;
if (left[2] != '-' || left[3] != '-')
return NULL;
if (right < string || right[-1] != '-' || right[-2] != '-')
return NULL;
// trim off end
right[-2] = 0;
left += 4;
// trim empty characters
while (*left && (*left == ' ' || *left == '\t'))
left ++;
return left;
}
bool CXmlElementTree::found_tag(char *string)
{
char *left, *right;
left = strchr(string, '<');
right = strchr(string, '>');
return (left && right && right > left);
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/opengnss/SignalSim.git
git@gitee.com:opengnss/SignalSim.git
opengnss
SignalSim
SignalSim
master

搜索帮助