⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmlnode.cpp

📁 可移植的xml库。已经在windows和linux上测试通过。只使用C++ Runtine
💻 CPP
📖 第 1 页 / 共 3 页
字号:
			case '+':
				if(!p->m_nod) return E_XML_NO_TAG;
				x = va_arg(ap,CXMLNode *);
				if(!x) return E_XML_BAD_ARG;
				if(child) p->appendChild(x);
				else p->appendSibling(x);
				p = x;
				break;
			case '*':
				if(p->m_flags & XNF_FULL_NODE) return E_XML_PENDING_ATTRIB;
				a = va_arg(ap,CXMLAttrib *);
				if(!a) return E_XML_BAD_ARG;
				p->appendAttrib(a);
				break;
			case '#':
				if(!p->m_nod) return E_XML_NO_TAG;
				s = va_arg(ap,const char *);
				if(!s || !*s) return E_XML_BAD_ARG;
				x = new CXMLNode;
				if(!x) return E_OUTOF_MEMORY;
				if((e=x->setNod(s))) return e;
				x->m_flags = XNT_CDATA;
				if(child) p->appendChild(x);
				else p->appendSibling(x);
				p = x;
				break;
			case '<':
				if(!p->m_nod) return E_XML_NO_TAG;
				if(fmt[1]=='/')
				{
					s = va_arg(ap,const char *);
					if(!s || !*s) return E_XML_BAD_ARG;
					len = strlen(s);
					p = p->findOpenTag(s,len);
					if(!p) return E_XML_BAD_TILE;
				}
				else
				{
					if((p->m_flags & XNF_INDEP_TAG) || p->m_type==XNT_META) child = false;
					x = new CXMLNode;
					if(!x) return E_OUTOF_MEMORY;
					if(child) p->appendChild(x);
					else p->appendSibling(x);
					p = x;
				}
				break;
			case ' ':
				if(!p->m_nod) return E_XML_NO_TAG;
				if(p->m_flags & XNF_FULL_NODE) return E_XML_PENDING_ATTRIB;
				break;
			case '/':
				if(!p->m_nod) return E_XML_NO_TAG;
				if(p->m_type!=XNT_TAG) return E_XML_CONFLICT_TYPES;
				if(p->m_flags & (XNF_CLOSE_TAG|XNF_INDEP_TAG)) return E_XML_CONFLICT_FLAGS;
				p->m_flags |= XNF_INDEP_TAG|XNF_FULL_NODE;
				break;
			case '>':
				if(!p->m_nod) return E_XML_NO_TAG;
				if(p->m_type!=XNT_TAG) return E_XML_CONFLICT_TYPES;
				if(p->m_type==XNT_META || (p->m_flags & XNF_INDEP_TAG))
				{
					if(!p->m_parent) return E_XML_BAD_TILE;
					p->m_flags |= XNF_FULL_NODE;
					p = p->m_parent;
				}
				break;
			case '!':
			case '?':
				if(p->m_flags || p->m_type==XNT_META) return E_XML_CONFLICT_TYPES;
				if(p->m_flags & XNF_FULL_NODE) return E_XML_PENDING_ATTRIB;
				p->m_flags = *fmt;
				p->m_type = XNT_META;
				break;
			case 'c':
			case 'd':
			case 'l':
			case 'n':
			case 'p':
			case 's':
			case 'u':
			case 'w':
			case 'x':
				if(p->m_flags & XNF_FULL_NODE) return E_XML_PENDING_ATTRIB;
				if(p->m_nod) formatAttrib(p,fmt,ap);
				else formatNod(xc,p,fmt,ap);
				break;
			default:return E_XML_BAD_FORMAT;
			}
		}
	}
	catch(...)
	{
		return E_ACCESS_VIOLATE;
	}
	return 0;
}

char* CXMLNode::toStr(char *p,CXMLCodec *xc) const
{
	assert(m_nod && p);
	//generate leading symbols
	if(m_type==XNT_CDATA && m_parent->m_children==1){}//no leading space
	else
	{
		unsigned bytes = m_depth * CXMLNode::m_indent;		//leading spaces for nicer looking
		for(;bytes;--bytes) *p++ = ' ';
	}
	if(m_type==XNT_TAG)
	{
		*p++ = '<';	//begin tag "<"
		if(m_flags & XNF_CLOSE_TAG) *p++ = '/';	//close tag "/"
	}
	else if(m_type==XNT_META)		//begin meta "<!", "<?"
	{
		*p++ = '<';
		*p++ = (char)m_flags;
	}
	else if(m_type==XNT_COMMENT)//"<!--"
	{
		*p++ = '<';
		*p++ = '!';
		*p++ = '-';
		*p++ = '-';
	}
	{//to reduce stack size
		//generate tag
		unsigned n = m_len;
		if(m_type==XNT_CDATA && xc) n = xc->xstrSize(m_nod,m_len);
		if(n==m_len)
		{
			memcpy(p,m_nod,m_len);
			p += m_len;
		}
		else p = xc->xencode(m_nod,m_len,p);
	}
	//generate attribute list
	if(m_attribs)
	{
		for(CXMLAttrib *a=m_head;a;a=a->getNext())
		{
			*p++ = ' ';//separator " "
			p = a->toStr(p);
		}
	}
	//generate ending symbols
	if(m_type==XNT_META)//end meta "!>", "?>"
	{
		*p++ = (char)m_flags;
		*p++ = '>';
	}
	else if(m_type==XNT_COMMENT)//"-->"
	{
		*p++ = '-';
		*p++ = '-';
		*p++ = '>';
	}
	else if(m_type==XNT_TAG)
	{
		if((m_flags & XNF_INDEP_TAG) || (!m_children && !(m_flags & XNF_CLOSE_TAG)))//end tag "/>"
		{
			*p++ = '/';
			*p++ = '>';
		}
		else *p++ = '>';//end tag ">"
	}
	//generate children node list
	if(m_children)
	{
		assert(m_type!=XNT_META && m_type!=XNT_CDATA && m_type!=XNT_COMMENT);
		assert(!(m_flags & XNF_INDEP_TAG));
		if(m_children==1 && m_first->m_type==XNT_CDATA){}//no line feed
		else if(CXMLNode::m_indent) *p++ = '\n';//"\n"
		p = m_first->toStr(p,xc);
		if(m_children==1 && m_first->m_type==XNT_CDATA){}//no line feed
		else if(CXMLNode::m_indent) *p++ = '\n';//"\n"
		//generate close tag
		if(m_type==XNT_TAG && !(m_flags & XNF_INDEP_TAG))//close tag "</tag>"
		{
			if(m_first->m_type==XNT_CDATA && m_children==1){}//no leading space
			else
			{
				unsigned bytes = m_depth * CXMLNode::m_indent;		//leading spaces for nicer looking
				for(;bytes;--bytes) *p++ = ' ';
			}
			*p++ = '<';
			*p++ = '/';
			memcpy(p,m_nod,m_len);
			p += m_len;
			*p++ = '>';
		}
	}
	//generate next sibling
	if(m_next)
	{
		if(CXMLNode::m_indent) *p++ = '\n';//line feed "\n" if pad leading space
		p = m_next->toStr(p,xc);
	}
	return p;
}

CXMLNode* CXMLNode::load(CXMLNodeCache *xnc,const char*& b,const char *e,int *err,CXMLCodec *xc)
{
	if(err) *err = E_OUTOF_MEMORY;
	CXMLNode *x = xnc ? xnc->reuse() : new CXMLNode;
	if(!x)
	{
		if(err && xnc && xnc->getAllocCount()>=xnc->getAllocLimit()) *err = E_BEYOND_LIMIT;
		return 0;
	}
	int r = x->load(b,e,xc);
	if(err) *err = r;
	return x;
}

int CXMLNode::save(FILE *fp,CXMLCodec *xc) const
{
	assert(m_nod && fp);
	if(m_type==XNT_CDATA && m_parent->m_children==1){}//no leading space
	else
	{
		unsigned bytes = m_depth * CXMLNode::m_indent;		//leading spaces for nicer looking
		for(;bytes;--bytes) if(fwrite(" ",1,1,fp)!=1) return E_XML_SAVE_WRITE;
	}
	if(m_type==XNT_TAG)//begin tag "<"
	{
		if(fwrite("<",1,1,fp)!=1) return E_XML_SAVE_WRITE;
		if(m_flags & XNF_CLOSE_TAG)
		{
			if(fwrite("/",1,1,fp)!=1) return E_XML_SAVE_WRITE;
		}
	}
	else if(m_type==XNT_META)		//begin meta "<!", "<?"
	{
		if(fwrite("<",1,1,fp)!=1
			|| fwrite(&m_flags,1,1,fp)!=1) return E_XML_SAVE_WRITE;
	}
	else if(m_type==XNT_COMMENT)//"<!--"
	{
		if(fwrite("<!--",1,4,fp)!=4) return E_XML_SAVE_WRITE;
	}
	{//to reduce stack size
		unsigned n = m_len;
		if(m_type==XNT_CDATA && xc) n = xc->xstrSize(m_nod,m_len);
		if(n==m_len)
		{
			if(fwrite(m_nod,1,m_len,fp)!=m_len) return E_XML_SAVE_WRITE;
		}
		else
		{
			char *p = new char[n];
			if(!p) return E_OUTOF_MEMORY;
			xc->xencode(m_nod,m_len,p);
			bool ok = fwrite(p,1,n,fp)==n;
			delete [] p;
			if(!ok) return E_XML_SAVE_WRITE;
		}
	}
	if(m_attribs)
	{
		for(CXMLAttrib *a=m_head;a;a=a->getNext())
		{
			//separator " "
			if(fwrite(" ",1,1,fp)!=1) return E_XML_SAVE_WRITE;
			int e = a->save(fp);
			if(e) return e;
		}
	}
	//generate ending symbols
	if(m_type==XNT_META)//end meta "!>", "?>"
	{
		if(fwrite(&m_flags,1,1,fp)!=1
			|| fwrite(">",1,1,fp)!=1) return E_XML_SAVE_WRITE;
	}
	else if(m_type==XNT_COMMENT)//"-->"
	{
		if(fwrite("-->",1,3,fp)!=3) return E_XML_SAVE_WRITE;
	}
	else if(m_type==XNT_TAG)
	{
		if((m_flags & XNF_INDEP_TAG) || (!m_children && !(m_flags & XNF_CLOSE_TAG)))//end tag "/>"
		{
			if(fwrite("/>",1,2,fp)!=2) return E_XML_SAVE_WRITE;
		}
		else if(fwrite(">",1,1,fp)!=1) return E_XML_SAVE_WRITE;//end tag ">"
	}
	if(m_children)
	{
		assert(m_type!=XNT_META && m_type!=XNT_CDATA && m_type!=XNT_COMMENT);
		assert(!(m_flags & XNF_INDEP_TAG));
		if(m_children==1 && m_first->m_type==XNT_CDATA){}//no line feed
		else if(CXMLNode::m_indent) if(fwrite("\n",1,1,fp)!=1) return E_XML_SAVE_WRITE;//"\n"
		int e = m_first->save(fp,xc);
		if(e) return e;
		if(m_children==1 && m_first->m_type==XNT_CDATA){}//no line feed
		else if(CXMLNode::m_indent) if(fwrite("\n",1,1,fp)!=1) return E_XML_SAVE_WRITE;//"\n"
		//generate close tag
		if(m_type==XNT_TAG && !(m_flags & XNF_INDEP_TAG))//close tag "</tag>"
		{
			if(m_first->m_type==XNT_CDATA && m_children==1){}//no leading space
			else
			{
				unsigned bytes = m_depth * CXMLNode::m_indent;		//leading spaces for nicer looking
				for(;bytes;--bytes) if(fwrite(" ",1,1,fp)!=1) return E_XML_SAVE_WRITE;
			}
			if(fwrite("</",1,2,fp)!=2
				|| fwrite(m_nod,1,m_len,fp)!=m_len
				|| fwrite(">",1,1,fp)!=1) return E_XML_SAVE_WRITE;
		}
	}
	if(m_next)
	{
		if(CXMLNode::m_indent && fwrite("\n",1,1,fp)!=1) return E_XML_SAVE_WRITE;//line feed "\n" if pad leading space
		int e = m_next->save(fp,xc);
		if(e) return e;
	}
	return 0;
}

int CXMLNode::save(const char *path,CXMLCodec *xc,bool overwrite) const
{
	if(!overwrite && !access(path,2)) return E_XML_FILE_EXIST;
	FILE *fp = fopen(path,"wb");
	if(!fp) return E_XML_SAVE_FILE;
	int e = save(fp,xc);
	fclose(fp);
	return e;
}

int CXMLNode::loadCData(const char*& b,const char *e,CXMLCodec *xc)
{
	//CData node has no child or attributes
	if(m_children){m_first->free();m_first=m_last=0;}
	if(m_attribs){m_head->free();m_head=m_tail=0;}
	--e;
	xmlSkipBlanksReverse(e);
	unsigned len = e - b + 1;
	assert(len);
	m_flags = XNF_FULL_NODE;
	m_type = XNT_CDATA;
	int err = replaceNod(b,len,xc);
	b = e + 1;
	return err;
}

int CXMLNode::loadComment(const char*& b,const char *e)
{
	assert(b[0]=='<' && b[1]=='!' && b[2]=='-' && b[3]=='-');
	assert(e[0]=='-' && e[1]=='-' && e[2]=='>');
	//CData node has no child or attributes
	if(m_children){m_first->free();m_first=m_last=0;}
	if(m_attribs){m_head->free();m_head=m_tail=0;}
	const char *s = b + 4;
	const char *t = e - 1;
	xmlSkipBlanks(s);
	xmlSkipBlanksReverse(t);
	for(;!xmlIsBlank(*t) && t<=e;++t);
	unsigned len = t - s;
	if(t<=s) return E_XML_EMPTY_COMMENT;
	m_flags = XNF_FULL_NODE;
	m_type = XNT_COMMENT;
	int err = replaceNod(s,len,0);
	b = e;
	return err;
}

int CXMLNode::loadTag(const char*& b,const char *e)
{
	assert(b && e && *b=='<' && *e=='>');
	const char *s = b + 1;
	const char *t = e - 1;
	m_type = XNT_TAG;
	m_flags = 0;
	xmlSkipBlanks(s);
	xmlSkipBlanksReverse(t);
	if(*s=='/')
	{
		if(*t=='/') return E_XML_BAD_CLOSE;
		++s;
		m_flags |= XNF_CLOSE_TAG;
	}
	else if((unsigned char)(*s)<0x80 && *s!='_' && !isalnum(*s))
	{
		assert(!(m_flags & XNF_CLOSE_TAG));
		if(*s!=*t) return E_XML_BAD_META;
		m_type = XNT_META;
		m_flags = *s;
		++s;
		--t;
	}
	if(s>t) return E_XML_NO_TAG;
	b = s;
	xmlSkipSymbol(s);
	int err = replaceNod(b,s-b,0);
	if(err) return err;
	xmlSkipBlanks(s);
	b = s;
	if(s>t) return 0;
	if(m_type!=XNT_META && (m_flags & XNF_CLOSE_TAG)) return E_XML_CLOSETAG_ATTRIB;//close tag with attributes is not allowed
	CXMLAttrib *a;
	CXMLAttribCache *xac = 0;
	if(m_xnc) xac = &m_xnc->getAttribCache();
	for(;s<=t;)
	{
		xmlSkipBlanks(s);
		b = s;
		if(s>t) break;
		if(*s=='/')
		{
			++s;
			xmlSkipBlanks(s);
			if(*s!='>' || s<=t) return E_XML_BAD_SLASH;
			m_flags |= XNF_INDEP_TAG|XNF_FULL_NODE;
			b = s;
			break;
		}
		if(xac)
		{
			if(!(a=xac->reuse()))
			{
				if(xac->getAllocLimit() && xac->getAllocCount()>=xac->getAllocLimit()) return E_BEYOND_LIMIT;
				else return E_OUTOF_MEMORY;
			}
		}
		else
		{
			if(!(a=new CXMLAttrib)) return E_OUTOF_MEMORY;
		}
		err = a->load(s,t);
		if(err==E_XML_META_ATTRIB && m_type==XNT_META) err = 0;
		if(err){a->free();return err;}
		appendAttrib(a);
		b = s;
	}
	return 0;
}

int CXMLNode::load(const char*& b,const char *e,CXMLCodec *xc)
{
	if(b[0]=='<')
	{
		if(b[1]=='!' && b[2]=='-' && b[3]=='-') return CXMLNode::loadComment(b,e);
		else return CXMLNode::loadTag(b,e);
	}
	else return CXMLNode::loadCData(b,e,xc);
}

int CXMLNode::findClosePos(const char*& p,const char **r)
{
	assert(p && r);
	*r = 0;
	const char *t = p;
	int e = 0;
	if(t[0]=='<' && t[1]=='!' && t[2]=='-' && t[3]=='-')
	{
		p = t;
		t = strstr(t+1,"-->");
		if(t) *r = t;
		return 0;
	}
	xmlSkipBlanks(p);
	if(!*p) return 0;
	if(*p=='<')
	{
		t = p;
		for(;*t;)
		{
			if(*t=='/')
			{
				++t;
				xmlSkipBlanks(t);
				if(!*t) return 0;
				xmlSkipSymbol(t);
				xmlSkipBlanks(t);
				if(!*t) return 0;
				if(*t!='>') return E_XML_BAD_SLASH;
			}
			if(*t=='<' || *t=='>')
			{
				if(t!=p){*r=t;return 0;}
				else ++t;
			}
			xmlSkipAttribName(t);
			xmlSkipBlanks(t);
			if(!*t) return 0;
			if(*t=='=')
			{
				++t;
				if((e=CXMLAttrib::skipValue(t,(char *)-1))!=0) return e;
				xmlSkipBlanks(t);
				if(!*t) return 0;
			}
		}
	}
	else
	{
		t = strchr(p+1,'<');
		if(t) *r = t;
	}
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -