[DEV] base of the exml parser ==> start to work corectly ==> some good ideas
This commit is contained in:
parent
4600e688b4
commit
31482734a7
@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license BSD v3 (see license file)
|
||||
*/
|
||||
|
||||
#include <exml/EXmlAttribute.h>
|
||||
#include <exml/debug.h>
|
||||
|
||||
bool exml::EXmlAttribute::Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos)
|
||||
{
|
||||
EXML_DEBUG("start parse : 'attribute'");
|
||||
// search end of the comment :
|
||||
int32_t lastElementName = _pos;
|
||||
for (int32_t iii=_pos; iii<_data.Size(); iii++) {
|
||||
_filePos += ivec2(1,0);
|
||||
DrawElementParsed(_data[iii], _filePos);
|
||||
if (_data[iii] == '\n') {
|
||||
_filePos.setValue(1, _filePos.y()+1);
|
||||
EXML_ERROR("unexpected '\\n' in an attribute parsing");
|
||||
return false;
|
||||
}
|
||||
if (true==CheckAvaillable(_data[iii], false) ) {
|
||||
lastElementName = iii;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_name = _data.Extract(_pos, lastElementName+1);
|
||||
|
||||
if (lastElementName+1>=_data.Size()) {
|
||||
EXML_ERROR(" parse an xml end with an attribute parsing...");
|
||||
return false;
|
||||
}
|
||||
if (_data[lastElementName+1] != '=') {
|
||||
EXML_ERROR(" error attribute parsing ==> missing '=' ...");
|
||||
return false;
|
||||
}
|
||||
if (lastElementName+2>=_data.Size()) {
|
||||
EXML_ERROR(" parse an xml end with an attribute parsing...");
|
||||
return false;
|
||||
}
|
||||
if (_data[lastElementName+2] != '"') {
|
||||
// parse with no element " ==> direct value separate with space ...
|
||||
_filePos += ivec2(2,0);
|
||||
int32_t lastAttributePos = lastElementName+3;
|
||||
for (int32_t iii=lastElementName+2; iii<_data.Size(); iii++) {
|
||||
_filePos += ivec2(1,0);
|
||||
DrawElementParsed(_data[iii], _filePos);
|
||||
if (_data[iii] == '\n') {
|
||||
_filePos.setValue(1, _filePos.y()+1);
|
||||
EXML_ERROR("unexpected '\\n' in an attribute parsing");
|
||||
return false;
|
||||
}
|
||||
if (_data[iii]!=' ') {
|
||||
lastAttributePos = iii;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_value = _data.Extract(lastElementName+2, lastAttributePos+1);
|
||||
|
||||
_pos = lastAttributePos+1;
|
||||
return true;
|
||||
}
|
||||
_filePos += ivec2(2,0);
|
||||
int32_t lastAttributePos = lastElementName+3;
|
||||
for (int32_t iii=lastElementName+3; iii<_data.Size(); iii++) {
|
||||
_filePos += ivec2(1,0);
|
||||
DrawElementParsed(_data[iii], _filePos);
|
||||
if (_data[iii] == '\n') {
|
||||
_filePos.setValue(1, _filePos.y()+1);
|
||||
EXML_ERROR("unexpected '\\n' in an attribute parsing");
|
||||
return false;
|
||||
}
|
||||
if (_data[iii]!='"') {
|
||||
lastAttributePos = iii;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_value = _data.Extract(lastElementName+3, lastAttributePos+1);
|
||||
|
||||
_pos = lastAttributePos+1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool exml::EXmlAttribute::Generate(etk::UString& _data, int32_t _indent)
|
||||
{
|
||||
_data += " ";
|
||||
_data += m_name;
|
||||
_data += "=\"";
|
||||
_data += m_value;
|
||||
_data += "\"";
|
||||
return true;
|
||||
}
|
@ -20,6 +20,8 @@ namespace exml
|
||||
EXmlAttribute(void) { };
|
||||
virtual ~EXmlAttribute(void) { };
|
||||
virtual nodeType_te GetType(void) { return exml::typeAttribute; };
|
||||
virtual bool Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos);
|
||||
virtual bool Generate(etk::UString& _data, int32_t _indent);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license BSD v3 (see license file)
|
||||
*/
|
||||
|
||||
#include <exml/EXmlComment.h>
|
||||
#include <exml/debug.h>
|
||||
|
||||
bool exml::EXmlComment::Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos)
|
||||
{
|
||||
EXML_DEBUG("start parse : 'comment'");
|
||||
// search end of the comment :
|
||||
for (int32_t iii=_pos; iii+2<_data.Size(); iii++) {
|
||||
_filePos += ivec2(1,0);
|
||||
DrawElementParsed(_data[iii], _filePos);
|
||||
if (_data[iii] == '\n') {
|
||||
_filePos.setValue(1, _filePos.y()+1);
|
||||
continue;
|
||||
}
|
||||
if( _data[iii] == '-'
|
||||
&& _data[iii+1] == '-'
|
||||
&& _data[iii+2] == '>') {
|
||||
// find end of value:
|
||||
m_value = _data.Extract(_pos, iii-1);
|
||||
EXML_DEBUG(" find comment '" << m_value << "'");
|
||||
_pos = iii+2;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_pos = _data.Size();
|
||||
EXML_ERROR("comment got end of file without finding end node");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool exml::EXmlComment::Generate(etk::UString& _data, int32_t _indent)
|
||||
{
|
||||
AddIndent(_data, _indent);
|
||||
_data += "<!--";
|
||||
_data += m_value;
|
||||
_data += "-->\n";
|
||||
return true;
|
||||
}
|
@ -14,12 +14,14 @@
|
||||
|
||||
namespace exml
|
||||
{
|
||||
class EXmlElement : public EXmlNode
|
||||
class EXmlComment : public EXmlNode
|
||||
{
|
||||
public:
|
||||
EXmlElement(void) { };
|
||||
virtual ~EXmlElement(void) { };
|
||||
EXmlComment(void) { };
|
||||
virtual ~EXmlComment(void) { };
|
||||
virtual nodeType_te GetType(void) { return typeAttribute; };
|
||||
virtual bool Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos);
|
||||
virtual bool Generate(etk::UString& _data, int32_t _indent);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,55 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license BSD v3 (see license file)
|
||||
*/
|
||||
|
||||
#include <exml/EXmlDeclaration.h>
|
||||
#include <exml/debug.h>
|
||||
|
||||
bool exml::EXmlDeclaration::Generate(etk::UString& _data, int32_t _indent)
|
||||
{
|
||||
AddIndent(_data, _indent);
|
||||
_data += "<?";
|
||||
_data += m_name;
|
||||
if (m_value.Size()!=0) {
|
||||
_data += " ";
|
||||
_data += m_value;
|
||||
}
|
||||
_data += "?>\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool exml::EXmlDeclaration::Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos)
|
||||
{
|
||||
EXML_DEBUG("start parse : 'declaration'");
|
||||
// search end of the comment :
|
||||
for (int32_t iii=_pos; iii+1<_data.Size(); iii++) {
|
||||
_filePos += ivec2(1,0);
|
||||
DrawElementParsed(_data[iii], _filePos);
|
||||
if (_data[iii] == '\n') {
|
||||
_filePos.setValue(1, _filePos.y()+1);
|
||||
continue;
|
||||
}
|
||||
if( _data[iii] == '>'
|
||||
|| _data[iii] == '<') {
|
||||
// an error occured :
|
||||
EXML_ERROR(_filePos << " find '>' or '<' instead of '?>'");
|
||||
return false;
|
||||
}
|
||||
if( _data[iii] == '?'
|
||||
&& _data[iii+1] == '>') {
|
||||
// find end of value:
|
||||
m_value = _data.Extract(_pos, iii-1);
|
||||
EXML_DEBUG(" find declaration '" << m_value << "'");
|
||||
_pos = iii;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_pos = _data.Size();
|
||||
EXML_ERROR("Text got end of file without finding end node");
|
||||
return false;
|
||||
}
|
||||
|
@ -20,6 +20,9 @@ namespace exml
|
||||
EXmlDeclaration(void) { };
|
||||
virtual ~EXmlDeclaration(void) { };
|
||||
virtual nodeType_te GetType(void) { return typeAttribute; };
|
||||
virtual bool Generate(etk::UString& _data, int32_t _indent);
|
||||
virtual bool Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos);
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <exml/EXmlDocument.h>
|
||||
#include <exml/debug.h>
|
||||
|
||||
|
||||
exml::EXmlDocument::EXmlDocument(void) :
|
||||
@ -16,13 +17,35 @@ exml::EXmlDocument::EXmlDocument(void) :
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool exml::EXmlDocument::Generate(etk::UString& _data, int32_t _indent)
|
||||
{
|
||||
for (int32_t iii=0; iii<m_listSub.Size(); iii++) {
|
||||
if (NULL!=m_listSub[iii]) {
|
||||
m_listSub[iii]->Generate(_data, _indent);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool exml::EXmlDocument::Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos)
|
||||
{
|
||||
EXML_DEBUG("start parse : 'document'");
|
||||
// in this case : no main node ...
|
||||
SubParse(_data, _pos, _caseSensitive, _filePos, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool exml::EXmlDocument::Parse(const etk::UString& _data)
|
||||
{
|
||||
EXML_DEBUG("Start parsing document (type: string) size=" << _data.Size());
|
||||
// came from char ==> force in utf8 ...
|
||||
m_charset = unicode::EDN_CHARSET_UTF8;
|
||||
ivec2 filePos(1,1);
|
||||
int32_t ret = exml::EXmlElement::Parse(_data, 0, m_caseSensitive, filePos);
|
||||
return false;
|
||||
ivec2 filePos(0,1);
|
||||
int32_t parsePos = 0;
|
||||
return Parse(_data, parsePos, m_caseSensitive, filePos);
|
||||
}
|
||||
|
||||
bool exml::EXmlDocument::Generate(etk::UString& _data)
|
||||
@ -40,4 +63,10 @@ bool exml::EXmlDocument::Store(const etk::UString& _file)
|
||||
return false;
|
||||
}
|
||||
|
||||
void exml::EXmlDocument::Display(void)
|
||||
{
|
||||
etk::UString tmpp;
|
||||
Generate(tmpp, 0);
|
||||
EXML_INFO("Generated XML : \n" << tmpp);
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,9 @@ namespace exml
|
||||
*/
|
||||
bool Store(const etk::UString& _file);
|
||||
|
||||
void Display(void);
|
||||
bool Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos);
|
||||
bool Generate(etk::UString& _data, int32_t _indent);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -8,6 +8,10 @@
|
||||
|
||||
#include <exml/EXmlElement.h>
|
||||
#include <exml/debug.h>
|
||||
#include <exml/EXmlText.h>
|
||||
#include <exml/EXmlComment.h>
|
||||
#include <exml/EXmlAttribute.h>
|
||||
#include <exml/EXmlDeclaration.h>
|
||||
|
||||
|
||||
exml::EXmlNode* exml::EXmlElement::GetSub(int32_t _id)
|
||||
@ -55,77 +59,308 @@ void exml::EXmlElement::AppendAttribute(exml::EXmlAttribute* _node)
|
||||
m_listAttribute.PushBack(_node);
|
||||
}
|
||||
|
||||
bool exml::EXmlElement::Parse(const etk::UString& _data, int32_t _pos, bool _caseSensitive, ivec2& _filePos, int32_t& findLen)
|
||||
|
||||
bool exml::EXmlElement::Generate(etk::UString& _data, int32_t _indent)
|
||||
{
|
||||
AddIndent(_data, _indent);
|
||||
_data += "<";
|
||||
_data += m_name;
|
||||
for (int32_t iii=0; iii<m_listAttribute.Size(); iii++) {
|
||||
if (NULL!=m_listAttribute[iii]) {
|
||||
m_listAttribute[iii]->Generate(_data, _indent);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_listSub.Size()>0) {
|
||||
if( m_listSub.Size()==1
|
||||
&& m_listSub[0] != NULL
|
||||
&& m_listSub[0]->GetType() == exml::typeText
|
||||
&& static_cast<exml::EXmlText*>(m_listSub[0])->CountLines()==1) {
|
||||
_data += ">";
|
||||
m_listSub[0]->Generate(_data,0);
|
||||
} else {
|
||||
_data += ">\n";
|
||||
|
||||
for (int32_t iii=0; iii<m_listSub.Size(); iii++) {
|
||||
if (NULL!=m_listSub[iii]) {
|
||||
m_listSub[iii]->Generate(_data, _indent+1);
|
||||
}
|
||||
}
|
||||
AddIndent(_data, _indent);
|
||||
}
|
||||
_data += "</";
|
||||
_data += m_name;
|
||||
_data += ">\n";
|
||||
} else {
|
||||
_data += "/>\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool exml::EXmlElement::SubParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos, bool _mainNode)
|
||||
{
|
||||
EXML_DEBUG(" start subParse ... " << _pos << " " << _filePos);
|
||||
for (int32_t iii=_pos; iii<_data.Size(); iii++) {
|
||||
_filePos += ivec2(1,0);
|
||||
DrawElementParsed(_data[iii], _filePos);
|
||||
if (_data[iii] == '<') {
|
||||
if (iii+1>=_data.Size()) {
|
||||
// TODO : an error occured ...
|
||||
return iii;
|
||||
int32_t white = CountWhiteChar(_data, iii+1);
|
||||
if (iii+white+1>=_data.Size()) {
|
||||
EXML_ERROR(_filePos << " ==> end file with '<' char ==> invalide XML");
|
||||
_pos = iii+white;
|
||||
return false;
|
||||
}
|
||||
// find the end of the balise :
|
||||
int32_t endPos = iii;
|
||||
for (int32_t jjj=iii+1; jjj<_data.Size(); jjj++) {
|
||||
if(_data[jjj] == '>') {
|
||||
endPos = jjj;
|
||||
break;
|
||||
// Detect type of the element:
|
||||
if(_data[iii+white+1] == '>') {
|
||||
EXML_ERROR(_filePos << " find '>' with no element in the element...");
|
||||
_pos = iii+white+1;
|
||||
return false;
|
||||
}
|
||||
if(_data[iii+white+1] == '?') {
|
||||
// Find declaration balise
|
||||
exml::EXmlDeclaration* declaration = new exml::EXmlDeclaration();
|
||||
if (NULL==declaration) {
|
||||
EXML_ERROR(_filePos << " Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
if (endPos == iii) {
|
||||
// TODO : an error occured ...
|
||||
return iii;
|
||||
_pos = iii+white+2;
|
||||
_filePos += ivec2(3+white,0);
|
||||
if (false==declaration->Parse(_data, _pos, _caseSensitive, _filePos)) {
|
||||
delete(declaration);
|
||||
return false;
|
||||
}
|
||||
int32_t sizeElement = endPos-iii;
|
||||
if( sizeElement>2
|
||||
&& _data[iii+1] == '?'
|
||||
&& _data[endPos-1] == '?') {
|
||||
// find declaration
|
||||
|
||||
// TODO : ...
|
||||
|
||||
iii = endPos;
|
||||
m_listSub.PushBack(declaration);
|
||||
continue;
|
||||
}
|
||||
if( sizeElement>5
|
||||
&& _data[iii+1] == '!'
|
||||
&& _data[iii+2] == '-'
|
||||
&& _data[iii+3] == '-'
|
||||
&& _data[endPos-2] == '-'
|
||||
&& _data[endPos-1] == '-') {
|
||||
// find comment
|
||||
// TODO : Change the end parsing ...
|
||||
if(_data[iii+white+1] == '!') {
|
||||
// Find special block element
|
||||
if (iii+white+2>=_data.Size()) {
|
||||
EXML_ERROR(_filePos << " ==> end file with '<!' chars ==> invalide XML");
|
||||
return false;
|
||||
}
|
||||
if(_data[iii+white+2] == '-') {
|
||||
if (iii+white+3>=_data.Size()) {
|
||||
EXML_ERROR(_filePos << " ==> end file with '<!-' chars ==> invalide XML");
|
||||
return false;
|
||||
}
|
||||
if(_data[iii+white+3] != '-') {
|
||||
EXML_ERROR(_filePos << " ==> element parse with '<!-" << _data[iii+3] << "' chars ==> invalide XML");
|
||||
return false;
|
||||
}
|
||||
// find comment:
|
||||
exml::EXmlComment* comment = new exml::EXmlComment();
|
||||
if (NULL==comment) {
|
||||
EXML_ERROR(_filePos << " Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = iii+white+4;
|
||||
_filePos += ivec2(3+white,0);
|
||||
if (false==comment->Parse(_data, _pos, _caseSensitive, _filePos)) {
|
||||
delete(comment);
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listSub.PushBack(comment);
|
||||
} else if (_data[iii+white+2] == '[') {
|
||||
if (iii+white+8>=_data.Size()) {
|
||||
EXML_ERROR(_filePos << " ==> end file with '<![' chars ==> invalide XML");
|
||||
return false;
|
||||
}
|
||||
if( _data[iii+white+3] != 'C'
|
||||
|| _data[iii+white+4] != 'D'
|
||||
|| _data[iii+white+5] != 'A'
|
||||
|| _data[iii+white+6] != 'T'
|
||||
|| _data[iii+white+7] != 'A'
|
||||
|| _data[iii+white+8] != '[') {
|
||||
EXML_ERROR(_filePos << " ==> element parse with '<![" << _data[iii+white+3] << _data[iii+white+4] << _data[iii+white+5] << _data[iii+white+6] << _data[iii+white+7] << _data[iii+white+8] << "' chars ==> invalide XML");
|
||||
return false;
|
||||
}
|
||||
// find text:
|
||||
exml::EXmlTextCDATA* text = new exml::EXmlTextCDATA();
|
||||
if (NULL==text) {
|
||||
EXML_ERROR(_filePos << " Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = iii+9+white;
|
||||
_filePos += ivec2(8+white,0);
|
||||
if (false==text->Parse(_data, _pos, _caseSensitive, _filePos)) {
|
||||
delete(text);
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listSub.PushBack(text);
|
||||
} else {
|
||||
EXML_ERROR(_filePos << " ==> end file with '<!" << _data[iii+white+2] << "' chars ==> invalide XML");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// TODO : ...
|
||||
|
||||
iii = endPos;
|
||||
continue;
|
||||
}
|
||||
// find a normal node ...
|
||||
// TODO : ...
|
||||
for (int32_t jjj=iii+1; jjj<_data.Size(); jjj++) {
|
||||
if(_data[jjj] == '>') {
|
||||
if(_data[iii+white+1] == '/') {
|
||||
//EXML_DEBUG("Generate node name : '" << _data[iii+1] << "'");
|
||||
int32_t endPosName = iii+white+1;
|
||||
// Generate element name ...
|
||||
for (int32_t jjj=iii+white+2; jjj<_data.Size(); jjj++) {
|
||||
if(true == CheckAvaillable(_data[jjj], false) ) {
|
||||
// we find the end ...
|
||||
iii = jjj;
|
||||
endPosName = jjj;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
etk::UString tmpname = _data.Extract(iii+white+2, endPosName+1);
|
||||
if( tmpname == m_name) {
|
||||
// find end of node :
|
||||
// find > element ...
|
||||
for (int32_t jjj=endPosName+1; jjj<_data.Size(); jjj++) {
|
||||
_filePos += ivec2(1,0);
|
||||
DrawElementParsed(_data[jjj], _filePos);
|
||||
if (_data[jjj] == '\n') {
|
||||
_filePos.setValue(0, _filePos.y()+1);
|
||||
continue;
|
||||
}
|
||||
if(_data[jjj] == '>') {
|
||||
_pos = jjj;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
EXML_ERROR(_filePos << " ==> end node error : '" << tmpname << "' != '" << m_name << "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (_data[iii+white+1] == '>') {
|
||||
// end of something ==> this is really bad
|
||||
EXML_ERROR(_filePos << " ==> find '>' chars ==> invalide XML");
|
||||
return false;
|
||||
}
|
||||
|
||||
if( true == CheckAvaillable(_data[iii+white+1], true) ) {
|
||||
//EXML_DEBUG("Generate node name : '" << _data[iii+1] << "'");
|
||||
int32_t endPosName = iii+white+1;
|
||||
// Generate element name ...
|
||||
for (int32_t jjj=iii+white+2; jjj<_data.Size(); jjj++) {
|
||||
if(true == CheckAvaillable(_data[jjj], false) ) {
|
||||
// we find the end ...
|
||||
endPosName = jjj;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
etk::UString tmpname = _data.Extract(iii+white+1, endPosName+1);
|
||||
//EXML_INFO("find node named : '" << tmpname << "'");
|
||||
// find text:
|
||||
exml::EXmlElement* element = new exml::EXmlElement();
|
||||
if (NULL==element) {
|
||||
EXML_ERROR(_filePos << " Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
element->SetName(tmpname);
|
||||
_pos = endPosName+1;
|
||||
_filePos += ivec2(endPosName,0);
|
||||
if (false==element->Parse(_data, _pos, _caseSensitive, _filePos)) {
|
||||
delete(element);
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listSub.PushBack(element);
|
||||
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
if (_data[iii] == '>') {
|
||||
EXML_ERROR(_filePos << " find elemement '>' ==> no reason to be here ...");
|
||||
return false;
|
||||
}
|
||||
// might to be data text ...
|
||||
if( _data[iii] == ' '
|
||||
&& _data[iii] == '\t'
|
||||
&& _data[iii] == '\n'
|
||||
&& _data[iii] == '\r') {
|
||||
if (_data[iii] == '\n') {
|
||||
_filePos.setValue(1, _filePos.y()+1);
|
||||
}else if( _data[iii] == ' '
|
||||
|| _data[iii] == '\t'
|
||||
|| _data[iii] == '\r') {
|
||||
// empty spaces ==> nothing to do ....
|
||||
|
||||
} else {
|
||||
// find data ==> parse it...
|
||||
exml::EXmlText* text = new exml::EXmlText();
|
||||
if (NULL==text) {
|
||||
EXML_ERROR(_filePos << " Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = iii;
|
||||
_filePos += ivec2(1,0);
|
||||
if (false==text->Parse(_data, _pos, _caseSensitive, _filePos)) {
|
||||
delete(text);
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listSub.PushBack(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _pos;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool exml::EXmlElement::Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos)
|
||||
{
|
||||
EXML_DEBUG("start parse : 'element' named='" << m_name << "'");
|
||||
// note : When start parsing the upper element must have set the value of the element and set the position after this one
|
||||
|
||||
// find a normal node ...
|
||||
for (int32_t iii=_pos; iii<_data.Size(); iii++) {
|
||||
_filePos += ivec2(1,0);
|
||||
if (_data[iii] == '\n') {
|
||||
_filePos.setValue(1, _filePos.y()+1);
|
||||
}
|
||||
EXML_DEBUG("parse : '" << _data[iii] << "'");
|
||||
if(_data[iii] == '>') {
|
||||
// we find the end ...
|
||||
_pos = iii+1;
|
||||
return exml::EXmlElement::SubParse(_data, _pos, _caseSensitive, _filePos, false);
|
||||
}
|
||||
if (_data[iii] == '/') {
|
||||
// standalone node or error...
|
||||
if (iii+1>=_data.Size()) {
|
||||
EXML_ERROR(" find end of files ... ==> bad case");
|
||||
return false;
|
||||
}
|
||||
if (_data[iii+1] == '>') {
|
||||
_pos = iii+1;
|
||||
return true;
|
||||
}
|
||||
// error
|
||||
EXML_ERROR("find / without > char ...");
|
||||
return false;
|
||||
}
|
||||
if (true == CheckAvaillable(_data[iii], true)) {
|
||||
// we find an attibute ==> create a new and parse it :
|
||||
exml::EXmlAttribute* attribute = new exml::EXmlAttribute();
|
||||
if (NULL==attribute) {
|
||||
EXML_ERROR(_filePos << " Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = iii;
|
||||
if (false==attribute->Parse(_data, _pos, _caseSensitive, _filePos)) {
|
||||
delete(attribute);
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listAttribute.PushBack(attribute);
|
||||
continue;
|
||||
}
|
||||
// TODO : Else ==> if not white ==> create an error ...
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -21,20 +21,23 @@ namespace exml
|
||||
EXmlElement(void) { };
|
||||
virtual ~EXmlElement(void) { };
|
||||
virtual nodeType_te GetType(void) { return typeElement; };
|
||||
private:
|
||||
etk::Vector<EXmlNode*> m_listSub;
|
||||
protected:
|
||||
etk::Vector<exml::EXmlNode*> m_listSub;
|
||||
public:
|
||||
int32_t SizeSub(void) const { return m_listSub.Size(); };
|
||||
EXmlNode* GetSub(int32_t _id);
|
||||
void AppendSub(EXmlNode* _node);
|
||||
private:
|
||||
etk::Vector<EXmlAttribute*> m_listAttribute;
|
||||
protected:
|
||||
etk::Vector<exml::EXmlAttribute*> m_listAttribute;
|
||||
public:
|
||||
int32_t SizeAttribute(void) const { return m_listSub.Size(); };
|
||||
EXmlAttribute* GetAttribute(int32_t _id);
|
||||
void AppendAttribute(EXmlAttribute* _node);
|
||||
public:
|
||||
virtual bool Parse(const etk::UString& _data, int32_t _pos, bool _caseSensitive, ivec2& _filePos, int32_t& findLen);
|
||||
virtual bool Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos);
|
||||
virtual bool Generate(etk::UString& _data, int32_t _indent);
|
||||
protected:
|
||||
bool SubParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos, bool _mainNode=false);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,93 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license BSD v3 (see license file)
|
||||
*/
|
||||
|
||||
#include <exml/EXmlNode.h>
|
||||
#include <exml/debug.h>
|
||||
|
||||
void exml::EXmlNode::AddIndent(etk::UString& _data, int32_t _indent)
|
||||
{
|
||||
for (int32_t iii=0; iii<_indent; iii++) {
|
||||
_data+="\t";
|
||||
}
|
||||
}
|
||||
|
||||
void exml::EXmlNode::DrawElementParsed(const etk::UniChar& _val, const ivec2& _filePos)
|
||||
{
|
||||
if (_val=='\n') {
|
||||
EXML_DEBUG(_filePos << " Parse '\\n'");
|
||||
} else if (_val=='\t') {
|
||||
EXML_DEBUG(_filePos << " Parse '\\t'");
|
||||
} else {
|
||||
EXML_DEBUG(_filePos << " Parse '" << _val << "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// !"#$%&'()*+,/;<=>?@[\]^`{|}~ ou une espace et ne peut pas commencer par -. ou un chiffre.
|
||||
bool exml::EXmlNode::CheckAvaillable(const etk::UniChar& _val, bool _firstChar)
|
||||
{
|
||||
if( _val == '!'
|
||||
|| _val == '"'
|
||||
|| _val == '#'
|
||||
|| _val == '$'
|
||||
|| _val == '%'
|
||||
|| _val == '&'
|
||||
|| _val == '\'' // '
|
||||
|| _val == '('
|
||||
|| _val == ')'
|
||||
|| _val == '*'
|
||||
|| _val == '+'
|
||||
|| _val == ','
|
||||
|| _val == '/'
|
||||
|| _val == ';'
|
||||
|| _val == '<'
|
||||
|| _val == '='
|
||||
|| _val == '>'
|
||||
|| _val == '?'
|
||||
|| _val == '@'
|
||||
|| _val == '['
|
||||
|| _val == '\\'
|
||||
|| _val == ']'
|
||||
|| _val == '^'
|
||||
|| _val == '`'
|
||||
|| _val == '{'
|
||||
|| _val == '|'
|
||||
|| _val == '}'
|
||||
|| _val == '~'
|
||||
|| _val == ' '
|
||||
|| _val == '\n'
|
||||
|| _val == '\t'
|
||||
|| _val == '\r') {
|
||||
return false;
|
||||
}
|
||||
if (true == _firstChar) {
|
||||
if( _val == '-'
|
||||
|| _val == '.'
|
||||
|| ( _val >= '0'
|
||||
&& _val <= '9') ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t exml::EXmlNode::CountWhiteChar(const etk::UString& _data, int32_t _pos)
|
||||
{
|
||||
int32_t white=0;
|
||||
for (int32_t iii=_pos; iii<_data.Size(); iii++) {
|
||||
if( _data[iii] == ' '
|
||||
|| _data[iii] == '\t'
|
||||
|| _data[iii] == '\n'
|
||||
|| _data[iii] == '\r') {
|
||||
white++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return white;
|
||||
}
|
@ -30,11 +30,14 @@ namespace exml
|
||||
public:
|
||||
EXmlNode(void) { };
|
||||
virtual ~EXmlNode(void) { };
|
||||
protected:
|
||||
void AddIndent(etk::UString& _data, int32_t _indent);
|
||||
public:
|
||||
/**
|
||||
* Parse the sub nodes and current nodes ...
|
||||
*/
|
||||
virtual bool Parse(const etk::UString& _data, int32_t _pos, bool _caseSensitive, ivec2& _filePos, int32_t& findLen) = 0;
|
||||
virtual bool Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos) = 0;
|
||||
virtual bool Generate(etk::UString& _data, int32_t _indent) { return true; };
|
||||
protected:
|
||||
etk::UString m_name;
|
||||
public:
|
||||
@ -47,6 +50,10 @@ namespace exml
|
||||
virtual const etk::UString& GetValue(void) { return m_value; };
|
||||
public:
|
||||
virtual nodeType_te GetType(void) { return typeNode; };
|
||||
protected:
|
||||
void DrawElementParsed(const etk::UniChar& _val, const ivec2& _firstChar);
|
||||
bool CheckAvaillable(const etk::UniChar& _val, bool _firstChar);
|
||||
int32_t CountWhiteChar(const etk::UString& _data, int32_t _pos);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2011, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license BSD v3 (see license file)
|
||||
*/
|
||||
|
||||
#include <exml/EXmlText.h>
|
||||
#include <exml/debug.h>
|
||||
|
||||
bool exml::EXmlText::Generate(etk::UString& _data, int32_t _indent)
|
||||
{
|
||||
_data += m_value;
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t exml::EXmlText::CountLines(void)
|
||||
{
|
||||
int32_t count = 1;
|
||||
for (int32_t iii=0; iii<m_value.Size(); iii++) {
|
||||
if(m_value[iii] == '\n') {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
bool exml::EXmlText::Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos)
|
||||
{
|
||||
EXML_DEBUG("start parse : 'text'");
|
||||
// search end of the comment :
|
||||
for (int32_t iii=_pos; iii<_data.Size(); iii++) {
|
||||
_filePos += ivec2(1,0);
|
||||
DrawElementParsed(_data[iii], _filePos);
|
||||
if (_data[iii] == '\n') {
|
||||
_filePos.setValue(0, _filePos.y()+1);
|
||||
continue;
|
||||
}
|
||||
if( _data[iii] == '>'
|
||||
|| _data[iii] == '<') {
|
||||
// search whitespace :
|
||||
int32_t newEnd=iii;
|
||||
for( int32_t jjj=iii-1; jjj>_pos; jjj--) {
|
||||
if( _data[jjj] == ' '
|
||||
|| _data[jjj] == '\n'
|
||||
|| _data[jjj] == '\r'
|
||||
|| _data[jjj] == '\t') {
|
||||
newEnd = jjj;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// find end of value:
|
||||
m_value = _data.Extract(_pos, newEnd);
|
||||
EXML_DEBUG(" find text '" << m_value << "'");
|
||||
_pos = iii-1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_pos = _data.Size();
|
||||
EXML_ERROR("Text got end of file without finding end node");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool exml::EXmlTextCDATA::Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos)
|
||||
{
|
||||
EXML_DEBUG("start parse : 'text::CDATA'");
|
||||
// search end of the comment :
|
||||
for (int32_t iii=_pos; iii+2<_data.Size(); iii++) {
|
||||
_filePos += ivec2(1,0);
|
||||
DrawElementParsed(_data[iii], _filePos);
|
||||
if (_data[iii] == '\n') {
|
||||
_filePos.setValue(1, _filePos.y()+1);
|
||||
continue;
|
||||
}
|
||||
if( _data[iii] == ']'
|
||||
&& _data[iii+1] == ']'
|
||||
&& _data[iii+2] == '>') {
|
||||
// find end of value:
|
||||
m_value = _data.Extract(_pos, iii-1);
|
||||
EXML_DEBUG(" find text CDATA '" << m_value << "'");
|
||||
_pos = iii+2;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_pos = _data.Size();
|
||||
EXML_ERROR("text CDATA got end of file without finding end node");
|
||||
return false;
|
||||
}
|
||||
|
@ -20,6 +20,17 @@ namespace exml
|
||||
EXmlText(void) { };
|
||||
virtual ~EXmlText(void) { };
|
||||
virtual nodeType_te GetType(void) { return typeText; };
|
||||
virtual bool Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos);
|
||||
virtual bool Generate(etk::UString& _data, int32_t _indent);
|
||||
int32_t CountLines(void);
|
||||
};
|
||||
class EXmlTextCDATA : public EXmlText
|
||||
{
|
||||
public:
|
||||
EXmlTextCDATA(void) { };
|
||||
virtual ~EXmlTextCDATA(void) { };
|
||||
virtual nodeType_te GetType(void) { return typeText; };
|
||||
virtual bool Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos);
|
||||
};
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user