[DEV] change coding style
This commit is contained in:
parent
75ef4d184a
commit
33d1e95085
@ -20,55 +20,55 @@ exml::Attribute::Attribute(const etk::UString& _name, const etk::UString& _value
|
||||
|
||||
}
|
||||
|
||||
bool exml::Attribute::IParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc)
|
||||
bool exml::Attribute::iParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc)
|
||||
{
|
||||
EXML_VERBOSE("start parse : 'attribute'");
|
||||
m_pos = _filePos;
|
||||
// search end of the comment :
|
||||
int32_t lastElementName = _pos;
|
||||
for (int32_t iii=_pos; iii<_data.Size(); iii++) {
|
||||
_filePos.Check(_data[iii]);
|
||||
for (int32_t iii=_pos; iii<_data.size(); iii++) {
|
||||
_filePos.check(_data[iii]);
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
DrawElementParsed(_data[iii], _filePos);
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if (true==CheckAvaillable(_data[iii], false) ) {
|
||||
if (true == checkAvaillable(_data[iii], false) ) {
|
||||
lastElementName = iii;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_name = _data.Extract(_pos, lastElementName+1);
|
||||
if (true==_caseSensitive) {
|
||||
m_name.Lower();
|
||||
m_name = _data.extract(_pos, lastElementName+1);
|
||||
if (true == _caseSensitive) {
|
||||
m_name.lower();
|
||||
}
|
||||
// count white space :
|
||||
exml::filePos tmpPos;
|
||||
int32_t white = CountWhiteChar(_data, lastElementName+1, tmpPos);
|
||||
int32_t white = countWhiteChar(_data, lastElementName+1, tmpPos);
|
||||
_filePos += tmpPos;
|
||||
if (lastElementName+white+1>=_data.Size()) {
|
||||
if (lastElementName+white+1>=_data.size()) {
|
||||
CREATE_ERROR(_doc, _data, lastElementName+white+1, _filePos, " parse an xml end with an attribute parsing...");
|
||||
return false;
|
||||
}
|
||||
if (_data[lastElementName+white+1] != '=') {
|
||||
CREATE_ERROR(_doc, _data, lastElementName+white+1, _filePos, " error attribute parsing ==> missing '=' ...");
|
||||
CREATE_ERROR(_doc, _data, lastElementName+white+1, _filePos, " error attribute parsing == > missing '=' ...");
|
||||
return false;
|
||||
}
|
||||
white += CountWhiteChar(_data, lastElementName+white+2, tmpPos);
|
||||
white += countWhiteChar(_data, lastElementName+white+2, tmpPos);
|
||||
_filePos += tmpPos;
|
||||
|
||||
if (lastElementName+white+2>=_data.Size()) {
|
||||
if (lastElementName+white+2>=_data.size()) {
|
||||
CREATE_ERROR(_doc, _data, lastElementName+white+2, _filePos, " parse an xml end with an attribute parsing...");
|
||||
return false;
|
||||
}
|
||||
if (_data[lastElementName+white+2] != '"') {
|
||||
// parse with no element " ==> direct value separate with space ...
|
||||
// parse with no element " == > direct value separate with space ...
|
||||
++_filePos;
|
||||
int32_t lastAttributePos = lastElementName+white+2;
|
||||
for (int32_t iii=lastElementName+white+2; iii<_data.Size(); iii++) {
|
||||
for (int32_t iii=lastElementName+white+2; iii<_data.size(); iii++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
DrawElementParsed(_data[iii], _filePos);
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if (_filePos.Check(_data[iii])==true) {
|
||||
if (_filePos.check(_data[iii]) == true) {
|
||||
CREATE_ERROR(_doc, _data, iii, _filePos, "unexpected '\\n' in an attribute parsing");
|
||||
return false;
|
||||
}
|
||||
@ -81,7 +81,7 @@ bool exml::Attribute::IParse(const etk::UString& _data, int32_t& _pos, bool _cas
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_value = _data.Extract(lastElementName+white+2, lastAttributePos);
|
||||
m_value = _data.extract(lastElementName+white+2, lastAttributePos);
|
||||
|
||||
EXML_PARSE_ATTRIBUTE(m_pos << " attribute : " << m_name << "=\"" << m_value << "\"");
|
||||
|
||||
@ -89,18 +89,18 @@ bool exml::Attribute::IParse(const etk::UString& _data, int32_t& _pos, bool _cas
|
||||
return true;
|
||||
}
|
||||
int32_t lastAttributePos = lastElementName+white+3;
|
||||
for (int32_t iii=lastElementName+white+3; iii<_data.Size(); iii++) {
|
||||
for (int32_t iii=lastElementName+white+3; iii<_data.size(); iii++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
DrawElementParsed(_data[iii], _filePos);
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
_filePos.Check(_data[iii]);
|
||||
_filePos.check(_data[iii]);
|
||||
if(_data[iii]!='"') {
|
||||
lastAttributePos = iii+1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_value = _data.Extract(lastElementName+white+3, lastAttributePos);
|
||||
m_value = _data.extract(lastElementName+white+3, lastAttributePos);
|
||||
|
||||
EXML_PARSE_ATTRIBUTE(m_pos << " attribute : " << m_name << "=\"" << m_value << "\"");
|
||||
|
||||
@ -108,7 +108,7 @@ bool exml::Attribute::IParse(const etk::UString& _data, int32_t& _pos, bool _cas
|
||||
return true;
|
||||
}
|
||||
|
||||
bool exml::Attribute::IGenerate(etk::UString& _data, int32_t _indent) const
|
||||
bool exml::Attribute::iGenerate(etk::UString& _data, int32_t _indent) const
|
||||
{
|
||||
_data += " ";
|
||||
_data += m_name;
|
||||
@ -120,7 +120,7 @@ bool exml::Attribute::IGenerate(etk::UString& _data, int32_t _indent) const
|
||||
|
||||
|
||||
|
||||
void exml::Attribute::Clear(void)
|
||||
void exml::Attribute::clear(void)
|
||||
{
|
||||
m_name="";
|
||||
}
|
||||
|
@ -35,22 +35,22 @@ namespace exml
|
||||
etk::UString m_name;
|
||||
public:
|
||||
/**
|
||||
* @brief Set the name of the attribute
|
||||
* @brief set the name of the attribute
|
||||
* @param[in] _name New name of the attribute
|
||||
*/
|
||||
virtual void SetName(etk::UString _name) { m_name = _name; };
|
||||
virtual void setName(etk::UString _name) { m_name = _name; };
|
||||
/**
|
||||
* @brief Get the current name of the Attribute
|
||||
* @brief get the current name of the Attribute
|
||||
* @return String of the attribute
|
||||
*/
|
||||
virtual const etk::UString& GetName(void) const { return m_name; };
|
||||
virtual const etk::UString& getName(void) const { return m_name; };
|
||||
public: // herited function:
|
||||
virtual nodeType_te GetType(void) const { return exml::typeAttribute; };
|
||||
virtual bool IParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc);
|
||||
virtual bool IGenerate(etk::UString& _data, int32_t _indent) const;
|
||||
virtual exml::Attribute* ToAttribute(void) { return this; };
|
||||
virtual const exml::Attribute* ToAttribute(void) const { return this; };
|
||||
virtual void Clear(void);
|
||||
virtual nodeType_te getType(void) const { return exml::typeAttribute; };
|
||||
virtual bool iParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc);
|
||||
virtual bool iGenerate(etk::UString& _data, int32_t _indent) const;
|
||||
virtual exml::Attribute* toAttribute(void) { return this; };
|
||||
virtual const exml::Attribute* toAttribute(void) const { return this; };
|
||||
virtual void clear(void);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -14,113 +14,113 @@
|
||||
|
||||
exml::AttributeList::~AttributeList(void)
|
||||
{
|
||||
for (int32_t iii=0; iii<m_listAttribute.Size(); iii++) {
|
||||
for (int32_t iii=0; iii<m_listAttribute.size(); iii++) {
|
||||
if (NULL!=m_listAttribute[iii]) {
|
||||
delete(m_listAttribute[iii]);
|
||||
m_listAttribute[iii]=NULL;
|
||||
}
|
||||
}
|
||||
m_listAttribute.Clear();
|
||||
m_listAttribute.clear();
|
||||
}
|
||||
|
||||
exml::Attribute* exml::AttributeList::GetAttr(int32_t _id)
|
||||
exml::Attribute* exml::AttributeList::getAttr(int32_t _id)
|
||||
{
|
||||
if (_id <0 || _id>m_listAttribute.Size()) {
|
||||
if (_id <0 || _id>m_listAttribute.size()) {
|
||||
return NULL;
|
||||
}
|
||||
return m_listAttribute[_id];
|
||||
}
|
||||
|
||||
const exml::Attribute* exml::AttributeList::GetAttr(int32_t _id) const
|
||||
const exml::Attribute* exml::AttributeList::getAttr(int32_t _id) const
|
||||
{
|
||||
if (_id <0 || _id>m_listAttribute.Size()) {
|
||||
if (_id <0 || _id>m_listAttribute.size()) {
|
||||
return NULL;
|
||||
}
|
||||
return m_listAttribute[_id];
|
||||
}
|
||||
|
||||
void exml::AttributeList::AppendAttribute(exml::Attribute* _attr)
|
||||
void exml::AttributeList::appendAttribute(exml::Attribute* _attr)
|
||||
{
|
||||
if (_attr == NULL) {
|
||||
EXML_ERROR("Try to set an empty node");
|
||||
return;
|
||||
}
|
||||
for (int32_t iii=0; iii<m_listAttribute.Size(); iii++) {
|
||||
for (int32_t iii=0; iii<m_listAttribute.size(); iii++) {
|
||||
if (m_listAttribute[iii] == _attr) {
|
||||
EXML_ERROR("Try to add a node that is already added befor !!!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_listAttribute.PushBack(_attr);
|
||||
m_listAttribute.pushBack(_attr);
|
||||
}
|
||||
|
||||
const etk::UString& exml::AttributeList::GetAttribute(const etk::UString& _name) const
|
||||
const etk::UString& exml::AttributeList::getAttribute(const etk::UString& _name) const
|
||||
{
|
||||
static const etk::UString errorReturn("");
|
||||
if (_name.Size()==0) {
|
||||
if (_name.size() == 0) {
|
||||
return errorReturn;
|
||||
}
|
||||
for (int32_t iii=0; iii<m_listAttribute.Size(); iii++) {
|
||||
for (int32_t iii=0; iii<m_listAttribute.size(); iii++) {
|
||||
if( NULL != m_listAttribute[iii]
|
||||
&& m_listAttribute[iii]->GetName() == _name) {
|
||||
return m_listAttribute[iii]->GetValue();
|
||||
&& m_listAttribute[iii]->getName() == _name) {
|
||||
return m_listAttribute[iii]->getValue();
|
||||
}
|
||||
}
|
||||
return errorReturn;
|
||||
}
|
||||
|
||||
bool exml::AttributeList::ExistAttribute(const etk::UString& _name) const
|
||||
bool exml::AttributeList::existAttribute(const etk::UString& _name) const
|
||||
{
|
||||
if (_name.Size()==0) {
|
||||
if (_name.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
for (int32_t iii=0; iii<m_listAttribute.Size(); iii++) {
|
||||
for (int32_t iii=0; iii<m_listAttribute.size(); iii++) {
|
||||
if( NULL != m_listAttribute[iii]
|
||||
&& m_listAttribute[iii]->GetName() == _name) {
|
||||
&& m_listAttribute[iii]->getName() == _name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void exml::AttributeList::SetAttribute(const etk::UString& _name, const etk::UString& _value)
|
||||
void exml::AttributeList::setAttribute(const etk::UString& _name, const etk::UString& _value)
|
||||
{
|
||||
// check if attribute already det :
|
||||
for (int32_t iii=0; iii<m_listAttribute.Size(); iii++) {
|
||||
for (int32_t iii=0; iii<m_listAttribute.size(); iii++) {
|
||||
if( NULL != m_listAttribute[iii]
|
||||
&& m_listAttribute[iii]->GetName() == _name) {
|
||||
&& m_listAttribute[iii]->getName() == _name) {
|
||||
// update the value :
|
||||
m_listAttribute[iii]->SetValue(_value);
|
||||
m_listAttribute[iii]->setValue(_value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
exml::Attribute* attr = new exml::Attribute(_name, _value);
|
||||
if (NULL==attr) {
|
||||
if (NULL == attr) {
|
||||
EXML_ERROR("memory allocation error...");
|
||||
}
|
||||
m_listAttribute.PushBack(attr);
|
||||
m_listAttribute.pushBack(attr);
|
||||
}
|
||||
|
||||
bool exml::AttributeList::IGenerate(etk::UString& _data, int32_t _indent) const
|
||||
bool exml::AttributeList::iGenerate(etk::UString& _data, int32_t _indent) const
|
||||
{
|
||||
for (int32_t iii=0; iii<m_listAttribute.Size(); iii++) {
|
||||
for (int32_t iii=0; iii<m_listAttribute.size(); iii++) {
|
||||
if (NULL!=m_listAttribute[iii]) {
|
||||
m_listAttribute[iii]->IGenerate(_data, _indent);
|
||||
m_listAttribute[iii]->iGenerate(_data, _indent);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void exml::AttributeList::Clear(void)
|
||||
void exml::AttributeList::clear(void)
|
||||
{
|
||||
exml::Node::Clear();
|
||||
for (int32_t iii=0; iii<m_listAttribute.Size(); iii++) {
|
||||
exml::Node::clear();
|
||||
for (int32_t iii=0; iii<m_listAttribute.size(); iii++) {
|
||||
if (NULL!=m_listAttribute[iii]) {
|
||||
delete(m_listAttribute[iii]);
|
||||
m_listAttribute[iii]=NULL;
|
||||
}
|
||||
}
|
||||
m_listAttribute.Clear();
|
||||
m_listAttribute.clear();
|
||||
}
|
||||
|
||||
|
||||
|
@ -35,43 +35,43 @@ namespace exml
|
||||
etk::Vector<exml::Attribute*> m_listAttribute; //!< list of all attribute
|
||||
public:
|
||||
/**
|
||||
* @brief Get the number of attribute in the Node
|
||||
* @brief get the number of attribute in the Node
|
||||
* @return Nulber of attribute >=0
|
||||
*/
|
||||
int32_t SizeAttribute(void) const { return m_listAttribute.Size(); };
|
||||
int32_t sizeAttribute(void) const { return m_listAttribute.size(); };
|
||||
/**
|
||||
* @brief Add attribute on the List
|
||||
* @brief add attribute on the List
|
||||
* @param[in] _attr Pointer on the attribute
|
||||
*/
|
||||
void AppendAttribute(exml::Attribute* _attr);
|
||||
void appendAttribute(exml::Attribute* _attr);
|
||||
/**
|
||||
* @brief Get attribute whith his ID
|
||||
* @param[in] _id Identifier of the attribute 0<= _id < SizeAttribute()
|
||||
* @brief get attribute whith his ID
|
||||
* @param[in] _id Identifier of the attribute 0<= _id < sizeAttribute()
|
||||
* @return Pointer on the attribute or NULL
|
||||
*/
|
||||
Attribute* GetAttr(int32_t _id);
|
||||
const Attribute* GetAttr(int32_t _id) const;
|
||||
Attribute* getAttr(int32_t _id);
|
||||
const Attribute* getAttr(int32_t _id) const;
|
||||
/**
|
||||
* @brief Get the attribute value with searching in the List with his name
|
||||
* @brief get the attribute value with searching in the List with his name
|
||||
* @param[in] _name Attribute Name.
|
||||
* @return Value of the attribute or no data in the string
|
||||
*/
|
||||
const etk::UString& GetAttribute(const etk::UString& _name) const;
|
||||
const etk::UString& getAttribute(const etk::UString& _name) const;
|
||||
/**
|
||||
* @brief Check if an attribute Exist or not with his name.
|
||||
* @brief check if an attribute exist or not with his name.
|
||||
* @param[in] _name Attribute Name.
|
||||
* @return true if the attribute exist or False
|
||||
*/
|
||||
bool ExistAttribute(const etk::UString& _name) const;
|
||||
bool existAttribute(const etk::UString& _name) const;
|
||||
/**
|
||||
* @brief Sen A new attribute or replace data of the previous one
|
||||
* @param[in] _name Name of the attribute
|
||||
* @param[in] _value Value of the attribute
|
||||
*/
|
||||
void SetAttribute(const etk::UString& _name, const etk::UString& _value);
|
||||
void setAttribute(const etk::UString& _name, const etk::UString& _value);
|
||||
public: // herited function:
|
||||
bool IGenerate(etk::UString& _data, int32_t _indent) const;
|
||||
virtual void Clear(void);
|
||||
bool iGenerate(etk::UString& _data, int32_t _indent) const;
|
||||
virtual void clear(void);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -13,19 +13,19 @@
|
||||
#undef __class__
|
||||
#define __class__ "Comment"
|
||||
|
||||
bool exml::Comment::IParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc)
|
||||
bool exml::Comment::iParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc)
|
||||
{
|
||||
EXML_VERBOSE("start parse : 'comment'");
|
||||
m_pos = _filePos;
|
||||
exml::filePos tmpPos;
|
||||
int32_t white = CountWhiteChar(_data, _pos, tmpPos);
|
||||
int32_t white = countWhiteChar(_data, _pos, tmpPos);
|
||||
_filePos += tmpPos;
|
||||
// search end of the comment :
|
||||
for (int32_t iii=_pos+white; iii+2<_data.Size(); iii++) {
|
||||
for (int32_t iii=_pos+white; iii+2<_data.size(); iii++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
DrawElementParsed(_data[iii], _filePos);
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if (_filePos.Check(_data[iii]) == true) {
|
||||
if (_filePos.check(_data[iii]) == true) {
|
||||
continue;
|
||||
}
|
||||
if( _data[iii] == '-'
|
||||
@ -35,27 +35,27 @@ bool exml::Comment::IParse(const etk::UString& _data, int32_t& _pos, bool _caseS
|
||||
// search whitespace :
|
||||
int32_t newEnd=iii;
|
||||
for( int32_t jjj=iii-1; jjj>_pos; jjj--) {
|
||||
if(true==_data[jjj].IsWhiteChar()) {
|
||||
if(true == _data[jjj].isWhiteChar()) {
|
||||
newEnd = jjj;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// find end of value:
|
||||
m_value = _data.Extract(_pos+white, newEnd);
|
||||
m_value = _data.extract(_pos+white, newEnd);
|
||||
EXML_VERBOSE(" find comment '" << m_value << "'");
|
||||
_pos = iii+2;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
_pos = _data.Size();
|
||||
_pos = _data.size();
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "comment got end of file without finding end node");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool exml::Comment::IGenerate(etk::UString& _data, int32_t _indent) const
|
||||
bool exml::Comment::iGenerate(etk::UString& _data, int32_t _indent) const
|
||||
{
|
||||
AddIndent(_data, _indent);
|
||||
addIndent(_data, _indent);
|
||||
_data += "<!--";
|
||||
_data += m_value;
|
||||
_data += "-->\n";
|
||||
|
@ -31,11 +31,11 @@ namespace exml
|
||||
*/
|
||||
virtual ~Comment(void) { };
|
||||
public: // herited function:
|
||||
virtual nodeType_te GetType(void) const { return typeAttribute; };
|
||||
virtual bool IParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc);
|
||||
virtual bool IGenerate(etk::UString& _data, int32_t _indent) const;
|
||||
virtual exml::Comment* ToComment(void) { return this; };
|
||||
virtual const exml::Comment* ToComment(void) const { return this; };
|
||||
virtual nodeType_te getType(void) const { return typeAttribute; };
|
||||
virtual bool iParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc);
|
||||
virtual bool iGenerate(etk::UString& _data, int32_t _indent) const;
|
||||
virtual exml::Comment* toComment(void) { return this; };
|
||||
virtual const exml::Comment* toComment(void) const { return this; };
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -23,42 +23,42 @@
|
||||
exml::DeclarationXML::DeclarationXML(const etk::UString& _version, unicode::charset_te _format, bool _standalone) :
|
||||
exml::Declaration("xml")
|
||||
{
|
||||
if (_version.Size()!=0) {
|
||||
SetAttribute("version", _version);
|
||||
if (_version.size()!=0) {
|
||||
setAttribute("version", _version);
|
||||
}
|
||||
if (_format!=unicode::EDN_CHARSET_UTF8) {
|
||||
SetAttribute("encoding", "UTF-8");
|
||||
setAttribute("encoding", "UTF-8");
|
||||
} else {
|
||||
EXML_ERROR("Actually does not supported other charset than UTF8");
|
||||
SetAttribute("encoding", "UTF-8");
|
||||
setAttribute("encoding", "UTF-8");
|
||||
}
|
||||
if (_standalone==true) {
|
||||
SetAttribute("standalone", "true");
|
||||
if (_standalone == true) {
|
||||
setAttribute("standalone", "true");
|
||||
} else {
|
||||
SetAttribute("standalone", "true");
|
||||
setAttribute("standalone", "true");
|
||||
}
|
||||
}
|
||||
|
||||
bool exml::Declaration::IGenerate(etk::UString& _data, int32_t _indent) const
|
||||
bool exml::Declaration::iGenerate(etk::UString& _data, int32_t _indent) const
|
||||
{
|
||||
AddIndent(_data, _indent);
|
||||
addIndent(_data, _indent);
|
||||
_data += "<?";
|
||||
_data += m_value;
|
||||
exml::AttributeList::IGenerate(_data, _indent);
|
||||
exml::AttributeList::iGenerate(_data, _indent);
|
||||
_data += "?>\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool exml::Declaration::IParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc)
|
||||
bool exml::Declaration::iParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc)
|
||||
{
|
||||
EXML_VERBOSE("start parse : 'declaration' : '" << m_value << "'");
|
||||
m_pos = _filePos;
|
||||
// search end of the comment :
|
||||
for (int32_t iii=_pos; iii+1<_data.Size(); iii++) {
|
||||
for (int32_t iii=_pos; iii+1<_data.size(); iii++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
DrawElementParsed(_data[iii], _filePos);
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if (_filePos.Check(_data[iii])==true) {
|
||||
if (_filePos.check(_data[iii]) == true) {
|
||||
continue;
|
||||
}
|
||||
if( _data[iii] == '>'
|
||||
@ -74,25 +74,25 @@ bool exml::Declaration::IParse(const etk::UString& _data, int32_t& _pos, bool _c
|
||||
_pos = iii+1;
|
||||
return true;
|
||||
}
|
||||
if (true == CheckAvaillable(_data[iii], true)) {
|
||||
// we find an attibute ==> create a new and parse it :
|
||||
if (true == checkAvaillable(_data[iii], true)) {
|
||||
// we find an attibute == > create a new and parse it :
|
||||
exml::Attribute* attribute = new exml::Attribute();
|
||||
if (NULL==attribute) {
|
||||
if (NULL == attribute) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, " Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = iii;
|
||||
if (false==attribute->IParse(_data, _pos, _caseSensitive, _filePos, _doc)) {
|
||||
if (false == attribute->iParse(_data, _pos, _caseSensitive, _filePos, _doc)) {
|
||||
delete(attribute);
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listAttribute.PushBack(attribute);
|
||||
m_listAttribute.pushBack(attribute);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Text got end of file without finding end node");
|
||||
_pos = _data.Size();
|
||||
_pos = _data.size();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -30,11 +30,11 @@ namespace exml
|
||||
*/
|
||||
virtual ~Declaration(void) { };
|
||||
public: // herited function:
|
||||
virtual nodeType_te GetType(void) const { return typeAttribute; };
|
||||
virtual bool IGenerate(etk::UString& _data, int32_t _indent) const;
|
||||
virtual bool IParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc);
|
||||
virtual exml::Declaration* ToDeclaration(void) { return this; };
|
||||
virtual const exml::Declaration* ToDeclaration(void) const { return this; };
|
||||
virtual nodeType_te getType(void) const { return typeAttribute; };
|
||||
virtual bool iGenerate(etk::UString& _data, int32_t _indent) const;
|
||||
virtual bool iParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc);
|
||||
virtual exml::Declaration* toDeclaration(void) { return this; };
|
||||
virtual const exml::Declaration* toDeclaration(void) const { return this; };
|
||||
};
|
||||
class DeclarationXML : public exml::Declaration
|
||||
{
|
||||
|
@ -25,50 +25,50 @@ exml::Document::Document(void) :
|
||||
}
|
||||
|
||||
|
||||
bool exml::Document::IGenerate(etk::UString& _data, int32_t _indent) const
|
||||
bool exml::Document::iGenerate(etk::UString& _data, int32_t _indent) const
|
||||
{
|
||||
for (int32_t iii=0; iii<m_listSub.Size(); iii++) {
|
||||
for (int32_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if (NULL!=m_listSub[iii]) {
|
||||
m_listSub[iii]->IGenerate(_data, _indent);
|
||||
m_listSub[iii]->iGenerate(_data, _indent);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool exml::Document::Parse(const etk::UString& _data)
|
||||
bool exml::Document::parse(const etk::UString& _data)
|
||||
{
|
||||
EXML_VERBOSE("Start parsing document (type: string) size=" << _data.Size());
|
||||
Clear();
|
||||
// came from char ==> force in utf8 ...
|
||||
EXML_VERBOSE("Start parsing document (type: string) size=" << _data.size());
|
||||
clear();
|
||||
// came from char == > force in utf8 ...
|
||||
m_charset = unicode::EDN_CHARSET_UTF8;
|
||||
exml::filePos filePos(1,0);
|
||||
m_pos = filePos;
|
||||
int32_t parsePos = 0;
|
||||
return SubParse(_data, parsePos, m_caseSensitive, filePos, *this, true);
|
||||
return subParse(_data, parsePos, m_caseSensitive, filePos, *this, true);
|
||||
}
|
||||
|
||||
bool exml::Document::Generate(etk::UString& _data)
|
||||
bool exml::Document::generate(etk::UString& _data)
|
||||
{
|
||||
_data = "";
|
||||
return IGenerate(_data,0);
|
||||
return iGenerate(_data,0);
|
||||
}
|
||||
|
||||
bool exml::Document::Load(const etk::UString& _file)
|
||||
bool exml::Document::load(const etk::UString& _file)
|
||||
{
|
||||
// Start loading the XML :
|
||||
EXML_VERBOSE("open file (xml) \"" << _file << "\"");
|
||||
Clear();
|
||||
clear();
|
||||
etk::FSNode tmpFile(_file);
|
||||
if (false == tmpFile.Exist()) {
|
||||
if (false == tmpFile.exist()) {
|
||||
EXML_ERROR("File Does not exist : " << _file);
|
||||
return false;
|
||||
}
|
||||
int64_t fileSize = tmpFile.FileSize();
|
||||
if (0==fileSize) {
|
||||
int64_t fileSize = tmpFile.fileSize();
|
||||
if (0 == fileSize) {
|
||||
EXML_ERROR("This file is empty : " << _file);
|
||||
return false;
|
||||
}
|
||||
if (false == tmpFile.FileOpenRead()) {
|
||||
if (false == tmpFile.fileOpenRead()) {
|
||||
EXML_ERROR("Can not open (r) the file : " << _file);
|
||||
return false;
|
||||
}
|
||||
@ -81,54 +81,54 @@ bool exml::Document::Load(const etk::UString& _file)
|
||||
// TODO : change this ... get the charset from the Declaration element ...
|
||||
memset(fileBuffer, 0, (fileSize+5)*sizeof(char));
|
||||
// load data from the file :
|
||||
tmpFile.FileRead(fileBuffer, 1, fileSize);
|
||||
tmpFile.fileRead(fileBuffer, 1, fileSize);
|
||||
// close the file:
|
||||
tmpFile.FileClose();
|
||||
tmpFile.fileClose();
|
||||
|
||||
// convert in UTF8 :
|
||||
etk::UString tmpDataUnicode(fileBuffer, unicode::EDN_CHARSET_UTF8);
|
||||
// remove temporary buffer:
|
||||
delete(fileBuffer);
|
||||
// parse the data :
|
||||
bool ret = Parse(tmpDataUnicode);
|
||||
bool ret = parse(tmpDataUnicode);
|
||||
//Display();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool exml::Document::Store(const etk::UString& _file)
|
||||
bool exml::Document::store(const etk::UString& _file)
|
||||
{
|
||||
etk::UString createData;
|
||||
if (false == Generate(createData)) {
|
||||
if (false == generate(createData)) {
|
||||
EXML_ERROR("Error while creating the XML : " << _file);
|
||||
return false;
|
||||
}
|
||||
etk::FSNode tmpFile(_file);
|
||||
if (false == tmpFile.FileOpenWrite()) {
|
||||
if (false == tmpFile.fileOpenWrite()) {
|
||||
EXML_ERROR("Can not open (w) the file : " << _file);
|
||||
return false;
|
||||
}
|
||||
etk::Char endTable = createData.c_str();
|
||||
if (tmpFile.FileWrite(endTable, sizeof(char), endTable.Size()) != endTable.Size()) {
|
||||
if (tmpFile.fileWrite(endTable, sizeof(char), endTable.size()) != endTable.size()) {
|
||||
EXML_ERROR("Error while writing output XML file : " << _file);
|
||||
tmpFile.FileClose();
|
||||
tmpFile.fileClose();
|
||||
return false;
|
||||
}
|
||||
tmpFile.FileClose();
|
||||
tmpFile.fileClose();
|
||||
return true;
|
||||
}
|
||||
|
||||
void exml::Document::Display(void)
|
||||
void exml::Document::display(void)
|
||||
{
|
||||
etk::UString tmpp;
|
||||
IGenerate(tmpp, 0);
|
||||
iGenerate(tmpp, 0);
|
||||
EXML_INFO("Generated XML : \n" << tmpp);
|
||||
}
|
||||
|
||||
etk::UString CreatePosPointer(const etk::UString& _line, int32_t _pos)
|
||||
etk::UString createPosPointer(const etk::UString& _line, int32_t _pos)
|
||||
{
|
||||
etk::UString out;
|
||||
int32_t iii;
|
||||
for (iii=0; iii<_pos && iii<_line.Size(); iii++) {
|
||||
for (iii=0; iii<_pos && iii<_line.size(); iii++) {
|
||||
if (_line[iii] == '\t') {
|
||||
out += "\t";
|
||||
} else {
|
||||
@ -142,27 +142,27 @@ etk::UString CreatePosPointer(const etk::UString& _line, int32_t _pos)
|
||||
return out;
|
||||
}
|
||||
|
||||
void exml::Document::DisplayError(void)
|
||||
void exml::Document::displayError(void)
|
||||
{
|
||||
if (m_comment.Size()==0) {
|
||||
if (m_comment.size() == 0) {
|
||||
EXML_ERROR("No error detected ???");
|
||||
return;
|
||||
}
|
||||
EXML_ERROR(m_filePos << " " << m_comment << "\n"
|
||||
<< m_Line << "\n"
|
||||
<< CreatePosPointer(m_Line, m_filePos.GetCol()) );
|
||||
<< createPosPointer(m_Line, m_filePos.getCol()) );
|
||||
#ifdef ENABLE_CRITICAL_WHEN_ERROR
|
||||
EXML_CRITICAL("detect error");
|
||||
#endif
|
||||
}
|
||||
|
||||
void exml::Document::CreateError(const etk::UString& _data, int32_t _pos, const exml::filePos& _filePos, const etk::UString& _comment)
|
||||
void exml::Document::createError(const etk::UString& _data, int32_t _pos, const exml::filePos& _filePos, const etk::UString& _comment)
|
||||
{
|
||||
m_comment = _comment;
|
||||
m_Line = _data.ExtractLine(_pos);
|
||||
m_Line = _data.extractLine(_pos);
|
||||
m_filePos = _filePos;
|
||||
if (true==m_writeErrorWhenDetexted) {
|
||||
DisplayError();
|
||||
if (true == m_writeErrorWhenDetexted) {
|
||||
displayError();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,15 +30,15 @@ namespace exml
|
||||
unicode::charset_te m_charset;
|
||||
public:
|
||||
/**
|
||||
* @brief Get the current charset of the Parsing
|
||||
* @brief get the current charset of the Parsing
|
||||
* @param[in] _charset The new charset
|
||||
*/
|
||||
virtual void SetCharset(unicode::charset_te _charset) { m_charset = _charset; };
|
||||
virtual void setCharset(unicode::charset_te _charset) { m_charset = _charset; };
|
||||
/**
|
||||
* @brief Get the current charset of the Parsing
|
||||
* @brief get the current charset of the Parsing
|
||||
* @return The current charset
|
||||
*/
|
||||
virtual unicode::charset_te GetCharset(void) const { return m_charset; };
|
||||
virtual unicode::charset_te getCharset(void) const { return m_charset; };
|
||||
private:
|
||||
bool m_caseSensitive; // check the case sensitive of the nodes and attribute
|
||||
public:
|
||||
@ -46,61 +46,61 @@ namespace exml
|
||||
* @brief Enable or diasable the case sensitive (must be done before the call of parsing)
|
||||
* @param[in] _val true if enable; false else.
|
||||
*/
|
||||
virtual void SetCaseSensitive(bool _val) { m_caseSensitive = _val; };
|
||||
virtual void setCaseSensitive(bool _val) { m_caseSensitive = _val; };
|
||||
/**
|
||||
* @brief Get the status of case sensitive mode.
|
||||
* @brief get the status of case sensitive mode.
|
||||
* @return true if case sensitive is active
|
||||
*/
|
||||
virtual bool GetCaseSensitive(void) const { return m_caseSensitive; };
|
||||
virtual bool getCaseSensitive(void) const { return m_caseSensitive; };
|
||||
public:
|
||||
/**
|
||||
* @brief Parse a string that contain an XML
|
||||
* @brief parse a string that contain an XML
|
||||
* @param[in] _data Data to parse
|
||||
* @return false : An error occured
|
||||
* @return true : Parsing is OK
|
||||
*/
|
||||
bool Parse(const etk::UString& _data);
|
||||
bool parse(const etk::UString& _data);
|
||||
/**
|
||||
* @brief Generate a string that contain the created XML
|
||||
* @brief generate a string that contain the created XML
|
||||
* @param[out] _data Data where the xml is stored
|
||||
* @return false : An error occured
|
||||
* @return true : Parsing is OK
|
||||
*/
|
||||
bool Generate(etk::UString& _data);
|
||||
bool generate(etk::UString& _data);
|
||||
/**
|
||||
* @brief Load the file that might contain the xml
|
||||
* @param[in] _file Filename of the xml (compatible with etk FSNode naming)
|
||||
* @return false : An error occured
|
||||
* @return true : Parsing is OK
|
||||
*/
|
||||
bool Load(const etk::UString& _file);
|
||||
bool load(const etk::UString& _file);
|
||||
/**
|
||||
* @brief Store the Xml in the file
|
||||
* @param[in] _file Filename of the xml (compatible with etk FSNode naming)
|
||||
* @return false : An error occured
|
||||
* @return true : Parsing is OK
|
||||
*/
|
||||
bool Store(const etk::UString& _file);
|
||||
bool store(const etk::UString& _file);
|
||||
/**
|
||||
* @brief Display the Document on console
|
||||
*/
|
||||
void Display(void);
|
||||
void display(void);
|
||||
private:
|
||||
bool m_writeErrorWhenDetexted;
|
||||
etk::UString m_comment;
|
||||
etk::UString m_Line;
|
||||
exml::filePos m_filePos;
|
||||
public:
|
||||
void DisplayErrorWhenDetected(void) { m_writeErrorWhenDetexted=true; };
|
||||
void NotDisplayErrorWhenDetected(void) { m_writeErrorWhenDetexted=false; };
|
||||
void displayErrorWhenDetected(void) { m_writeErrorWhenDetexted=true; };
|
||||
void notDisplayErrorWhenDetected(void) { m_writeErrorWhenDetexted=false; };
|
||||
|
||||
void CreateError(const etk::UString& _data, int32_t _pos, const exml::filePos& _filePos, const etk::UString& _comment);
|
||||
void DisplayError(void);
|
||||
void createError(const etk::UString& _data, int32_t _pos, const exml::filePos& _filePos, const etk::UString& _comment);
|
||||
void displayError(void);
|
||||
public: // herited function:
|
||||
virtual nodeType_te GetType(void) const { return typeDocument; };
|
||||
bool IGenerate(etk::UString& _data, int32_t _indent) const;
|
||||
virtual exml::Document* ToDocument(void) { return this; };
|
||||
virtual const exml::Document* ToDocument(void) const { return this; };
|
||||
virtual nodeType_te getType(void) const { return typeDocument; };
|
||||
bool iGenerate(etk::UString& _data, int32_t _indent) const;
|
||||
virtual exml::Document* toDocument(void) { return this; };
|
||||
virtual const exml::Document* toDocument(void) const { return this; };
|
||||
};
|
||||
};
|
||||
|
||||
@ -108,12 +108,12 @@ namespace exml
|
||||
#define CREATE_ERROR(doc,data,pos,filePos,comment) \
|
||||
EXML_ERROR( (pos) << " " << (comment) << "\n" \
|
||||
<< (data).ExtractLine((pos)) << "\n" \
|
||||
<< CreatePosPointer((filePos).GetCol()) )
|
||||
<< CreatePosPointer((filePos).getCol()) )
|
||||
*/
|
||||
#define CREATE_ERROR(doc,data,pos,filePos,comment) \
|
||||
do { \
|
||||
EXML_ERROR(comment); \
|
||||
(doc).CreateError((data),(pos),(filePos),(comment)); \
|
||||
(doc).createError((data),(pos),(filePos),(comment)); \
|
||||
} while (0)
|
||||
|
||||
//__LINE__, __class__, __func__
|
||||
|
282
exml/Element.cpp
282
exml/Element.cpp
@ -18,161 +18,155 @@
|
||||
#define __class__ "Element"
|
||||
|
||||
|
||||
exml::Element::~Element(void)
|
||||
{
|
||||
for (int32_t iii=0; iii<m_listSub.Size(); iii++) {
|
||||
exml::Element::~Element(void) {
|
||||
for (int32_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if (NULL!=m_listSub[iii]) {
|
||||
delete(m_listSub[iii]);
|
||||
m_listSub[iii]=NULL;
|
||||
}
|
||||
}
|
||||
m_listSub.Clear();
|
||||
m_listSub.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
exml::nodeType_te exml::Element::GetType(int32_t _id)
|
||||
{
|
||||
exml::Node* tmpp = GetNode(_id);
|
||||
if (NULL==tmpp) {
|
||||
exml::nodeType_te exml::Element::getType(int32_t _id) {
|
||||
exml::Node* tmpp = getNode(_id);
|
||||
if (NULL == tmpp) {
|
||||
return exml::typeUnknow;
|
||||
}
|
||||
return tmpp->GetType();
|
||||
return tmpp->getType();
|
||||
}
|
||||
const exml::nodeType_te exml::Element::GetType(int32_t _id) const
|
||||
{
|
||||
const exml::Node* tmpp = GetNode(_id);
|
||||
if (NULL==tmpp) {
|
||||
const exml::nodeType_te exml::Element::getType(int32_t _id) const {
|
||||
const exml::Node* tmpp = getNode(_id);
|
||||
if (NULL == tmpp) {
|
||||
return exml::typeUnknow;
|
||||
}
|
||||
return tmpp->GetType();
|
||||
return tmpp->getType();
|
||||
}
|
||||
|
||||
|
||||
exml::Node* exml::Element::GetNode(int32_t _id)
|
||||
{
|
||||
if (_id <0 || _id>m_listSub.Size()) {
|
||||
exml::Node* exml::Element::getNode(int32_t _id) {
|
||||
if (_id <0 || _id>m_listSub.size()) {
|
||||
return NULL;
|
||||
}
|
||||
return m_listSub[_id];
|
||||
}
|
||||
const exml::Node* exml::Element::GetNode(int32_t _id) const
|
||||
|
||||
const exml::Node* exml::Element::getNode(int32_t _id) const
|
||||
{
|
||||
if (_id <0 || _id>m_listSub.Size()) {
|
||||
if (_id <0 || _id>m_listSub.size()) {
|
||||
return NULL;
|
||||
}
|
||||
return m_listSub[_id];
|
||||
}
|
||||
|
||||
|
||||
exml::Element* exml::Element::GetElement(int32_t _id)
|
||||
exml::Element* exml::Element::getElement(int32_t _id)
|
||||
{
|
||||
exml::Node* tmpp = GetNode(_id);
|
||||
if (NULL==tmpp) {
|
||||
exml::Node* tmpp = getNode(_id);
|
||||
if (NULL == tmpp) {
|
||||
return NULL;
|
||||
}
|
||||
return tmpp->ToElement();
|
||||
return tmpp->toElement();
|
||||
}
|
||||
const exml::Element* exml::Element::GetElement(int32_t _id) const
|
||||
const exml::Element* exml::Element::getElement(int32_t _id) const
|
||||
{
|
||||
const exml::Node* tmpp = GetNode(_id);
|
||||
if (NULL==tmpp) {
|
||||
const exml::Node* tmpp = getNode(_id);
|
||||
if (NULL == tmpp) {
|
||||
return NULL;
|
||||
}
|
||||
return tmpp->ToElement();
|
||||
return tmpp->toElement();
|
||||
}
|
||||
|
||||
|
||||
exml::Element* exml::Element::GetNamed(const etk::UString& _name)
|
||||
exml::Element* exml::Element::getNamed(const etk::UString& _name)
|
||||
{
|
||||
if (_name.Size()==0) {
|
||||
if (_name.size() == 0) {
|
||||
return NULL;
|
||||
}
|
||||
for (int32_t iii=0; iii<m_listSub.Size(); iii++) {
|
||||
for (int32_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if( NULL != m_listSub[iii]
|
||||
&& m_listSub[iii]->GetType() == exml::typeElement
|
||||
&& m_listSub[iii]->GetValue() == _name) {
|
||||
if (NULL==m_listSub[iii]) {
|
||||
&& m_listSub[iii]->getType() == exml::typeElement
|
||||
&& m_listSub[iii]->getValue() == _name) {
|
||||
if (NULL == m_listSub[iii]) {
|
||||
return NULL;
|
||||
}
|
||||
return m_listSub[iii]->ToElement();
|
||||
return m_listSub[iii]->toElement();
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
const exml::Element* exml::Element::GetNamed(const etk::UString& _name) const
|
||||
const exml::Element* exml::Element::getNamed(const etk::UString& _name) const
|
||||
{
|
||||
if (_name.Size()==0) {
|
||||
if (_name.size() == 0) {
|
||||
return NULL;
|
||||
}
|
||||
for (int32_t iii=0; iii<m_listSub.Size(); iii++) {
|
||||
for (int32_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if( NULL != m_listSub[iii]
|
||||
&& m_listSub[iii]->GetType() == exml::typeElement
|
||||
&& m_listSub[iii]->GetValue() == _name) {
|
||||
if (NULL==m_listSub[iii]) {
|
||||
&& m_listSub[iii]->getType() == exml::typeElement
|
||||
&& m_listSub[iii]->getValue() == _name) {
|
||||
if (NULL == m_listSub[iii]) {
|
||||
return NULL;
|
||||
}
|
||||
return m_listSub[iii]->ToElement();
|
||||
return m_listSub[iii]->toElement();
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void exml::Element::Append(exml::Node* _node)
|
||||
void exml::Element::append(exml::Node* _node)
|
||||
{
|
||||
if (_node == NULL) {
|
||||
EXML_ERROR("Try to set an empty node");
|
||||
return;
|
||||
}
|
||||
if (_node->GetType()==exml::typeAttribute) {
|
||||
AppendAttribute(_node->ToAttribute());
|
||||
if (_node->getType() == exml::typeAttribute) {
|
||||
appendAttribute(_node->toAttribute());
|
||||
return;
|
||||
}
|
||||
for (int32_t iii=0; iii<m_listSub.Size(); iii++) {
|
||||
for (int32_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if (m_listSub[iii] == _node) {
|
||||
EXML_ERROR("Try to add a node that is already added before !!!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_listSub.PushBack(_node);
|
||||
m_listSub.pushBack(_node);
|
||||
}
|
||||
|
||||
etk::UString exml::Element::GetText(void)
|
||||
etk::UString exml::Element::getText(void)
|
||||
{
|
||||
// TODO : Add more capabilities ...
|
||||
// TODO : add more capabilities ...
|
||||
etk::UString res;
|
||||
for (int32_t iii=0; iii<m_listSub.Size(); iii++) {
|
||||
for (int32_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if (NULL!=m_listSub[iii]) {
|
||||
m_listSub[iii]->IGenerate(res, 0);
|
||||
m_listSub[iii]->iGenerate(res, 0);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool exml::Element::IGenerate(etk::UString& _data, int32_t _indent) const
|
||||
bool exml::Element::iGenerate(etk::UString& _data, int32_t _indent) const
|
||||
{
|
||||
AddIndent(_data, _indent);
|
||||
addIndent(_data, _indent);
|
||||
_data += "<";
|
||||
_data += m_value;
|
||||
exml::AttributeList::IGenerate(_data, _indent);
|
||||
exml::AttributeList::iGenerate(_data, _indent);
|
||||
|
||||
if (m_listSub.Size()>0) {
|
||||
if( m_listSub.Size()==1
|
||||
if (m_listSub.size()>0) {
|
||||
if( m_listSub.size() == 1
|
||||
&& m_listSub[0] != NULL
|
||||
&& m_listSub[0]->GetType() == exml::typeText
|
||||
&& static_cast<exml::Text*>(m_listSub[0])->CountLines()==1) {
|
||||
&& m_listSub[0]->getType() == exml::typeText
|
||||
&& static_cast<exml::Text*>(m_listSub[0])->countLines() == 1) {
|
||||
_data += ">";
|
||||
m_listSub[0]->IGenerate(_data,0);
|
||||
m_listSub[0]->iGenerate(_data,0);
|
||||
} else {
|
||||
_data += ">\n";
|
||||
|
||||
for (int32_t iii=0; iii<m_listSub.Size(); iii++) {
|
||||
for (int32_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if (NULL!=m_listSub[iii]) {
|
||||
m_listSub[iii]->IGenerate(_data, _indent+1);
|
||||
m_listSub[iii]->iGenerate(_data, _indent+1);
|
||||
}
|
||||
}
|
||||
AddIndent(_data, _indent);
|
||||
addIndent(_data, _indent);
|
||||
}
|
||||
_data += "</";
|
||||
_data += m_value;
|
||||
@ -184,20 +178,20 @@ bool exml::Element::IGenerate(etk::UString& _data, int32_t _indent) const
|
||||
}
|
||||
|
||||
|
||||
bool exml::Element::SubParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc, bool _mainNode)
|
||||
bool exml::Element::subParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc, bool _mainNode)
|
||||
{
|
||||
EXML_PARSE_ELEMENT(" start subParse ... " << _pos << " " << _filePos);
|
||||
for (int32_t iii=_pos; iii<_data.Size(); iii++) {
|
||||
_filePos.Check(_data[iii]);
|
||||
for (int32_t iii=_pos; iii<_data.size(); iii++) {
|
||||
_filePos.check(_data[iii]);
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
DrawElementParsed(_data[iii], _filePos);
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
exml::filePos tmpPos;
|
||||
if (_data[iii] == '<') {
|
||||
int32_t white = CountWhiteChar(_data, iii+1, tmpPos);
|
||||
if (iii+white+1>=_data.Size()) {
|
||||
int32_t white = countWhiteChar(_data, iii+1, tmpPos);
|
||||
if (iii+white+1>=_data.size()) {
|
||||
_filePos+=tmpPos;
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "End file with '<' char ==> invalide XML");
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "End file with '<' char == > invalide XML");
|
||||
_pos = iii+white;
|
||||
return false;
|
||||
}
|
||||
@ -211,79 +205,79 @@ bool exml::Element::SubParse(const etk::UString& _data, int32_t& _pos, bool _cas
|
||||
if(_data[iii+white+1] == '?') {
|
||||
++tmpPos;
|
||||
// TODO : white space ...
|
||||
if( false == CheckAvaillable(_data[iii+white+2], true) ) {
|
||||
if( false == checkAvaillable(_data[iii+white+2], true) ) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find unavaillable name in the Declaration node...");
|
||||
_pos = iii+white+1;
|
||||
return false;
|
||||
}
|
||||
//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) ) {
|
||||
// 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;
|
||||
}
|
||||
tmpPos.Check(_data[jjj]);
|
||||
tmpPos.check(_data[jjj]);
|
||||
}
|
||||
etk::UString tmpname = _data.Extract(iii+white+2, endPosName+1);
|
||||
if (true==_caseSensitive) {
|
||||
tmpname.Lower();
|
||||
etk::UString tmpname = _data.extract(iii+white+2, endPosName+1);
|
||||
if (true == _caseSensitive) {
|
||||
tmpname.lower();
|
||||
}
|
||||
// Find declaration balise
|
||||
exml::Declaration* declaration = new exml::Declaration(tmpname);
|
||||
if (NULL==declaration) {
|
||||
if (NULL == declaration) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Allocation Error...");
|
||||
return false;
|
||||
}
|
||||
_filePos += tmpPos;
|
||||
_pos = endPosName+1;
|
||||
if (false==declaration->IParse(_data, _pos, _caseSensitive, _filePos, _doc)) {
|
||||
if (false == declaration->iParse(_data, _pos, _caseSensitive, _filePos, _doc)) {
|
||||
delete(declaration);
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listSub.PushBack(declaration);
|
||||
m_listSub.pushBack(declaration);
|
||||
continue;
|
||||
}
|
||||
if(_data[iii+white+1] == '!') {
|
||||
++tmpPos;
|
||||
// Find special block element
|
||||
if (iii+white+2>=_data.Size()) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "End file with '<!' chars ==> invalide XML");
|
||||
if (iii+white+2>=_data.size()) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "End file with '<!' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
if(_data[iii+white+2] == '-') {
|
||||
++tmpPos;
|
||||
if (iii+white+3>=_data.Size()) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "End file with '<!-' chars ==> invalide XML");
|
||||
if (iii+white+3>=_data.size()) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "End file with '<!-' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
if(_data[iii+white+3] != '-') {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, etk::UString("Element parse with '<!-") + _data[iii+3] + "' chars ==> invalide XML");
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, etk::UString("Element parse with '<!-") + _data[iii+3] + "' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
++tmpPos;
|
||||
// find comment:
|
||||
exml::Comment* comment = new exml::Comment();
|
||||
if (NULL==comment) {
|
||||
if (NULL == comment) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = iii+white+4;
|
||||
_filePos += tmpPos;
|
||||
if (false==comment->IParse(_data, _pos, _caseSensitive, _filePos, _doc)) {
|
||||
if (false == comment->iParse(_data, _pos, _caseSensitive, _filePos, _doc)) {
|
||||
delete(comment);
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listSub.PushBack(comment);
|
||||
m_listSub.pushBack(comment);
|
||||
} else if (_data[iii+white+2] == '[') {
|
||||
++tmpPos;
|
||||
if (iii+white+8>=_data.Size()) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "End file with '<![' chars ==> invalide XML");
|
||||
if (iii+white+8>=_data.size()) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "End file with '<![' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
if( _data[iii+white+3] != 'C'
|
||||
@ -292,26 +286,26 @@ bool exml::Element::SubParse(const etk::UString& _data, int32_t& _pos, bool _cas
|
||||
|| _data[iii+white+6] != 'T'
|
||||
|| _data[iii+white+7] != 'A'
|
||||
|| _data[iii+white+8] != '[') {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, etk::UString("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");
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, etk::UString("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;
|
||||
}
|
||||
tmpPos+=6;
|
||||
// find text:
|
||||
exml::TextCDATA* text = new exml::TextCDATA();
|
||||
if (NULL==text) {
|
||||
if (NULL == text) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = iii+9+white;
|
||||
_filePos += tmpPos;
|
||||
if (false==text->IParse(_data, _pos, _caseSensitive, _filePos, _doc)) {
|
||||
if (false == text->iParse(_data, _pos, _caseSensitive, _filePos, _doc)) {
|
||||
delete(text);
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listSub.PushBack(text);
|
||||
m_listSub.pushBack(text);
|
||||
} else {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, etk::UString("End file with '<!") + _data[iii+white+2] + "' chars ==> invalide XML");
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, etk::UString("End file with '<!") + _data[iii+white+2] + "' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -321,28 +315,28 @@ bool exml::Element::SubParse(const etk::UString& _data, int32_t& _pos, bool _cas
|
||||
++tmpPos;
|
||||
//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) ) {
|
||||
// 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;
|
||||
}
|
||||
tmpPos.Check(_data[jjj]);
|
||||
tmpPos.check(_data[jjj]);
|
||||
}
|
||||
etk::UString tmpname = _data.Extract(iii+white+2, endPosName+1);
|
||||
if (true==_caseSensitive) {
|
||||
tmpname.Lower();
|
||||
etk::UString tmpname = _data.extract(iii+white+2, endPosName+1);
|
||||
if (true == _caseSensitive) {
|
||||
tmpname.lower();
|
||||
}
|
||||
if( tmpname == m_value) {
|
||||
// find end of node :
|
||||
// find > element ...
|
||||
for (int32_t jjj=endPosName+1; jjj<_data.Size(); jjj++) {
|
||||
for (int32_t jjj=endPosName+1; jjj<_data.size(); jjj++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
DrawElementParsed(_data[jjj], _filePos);
|
||||
drawElementParsed(_data[jjj], _filePos);
|
||||
#endif
|
||||
if (true==tmpPos.Check(_data[jjj])) {
|
||||
if (true == tmpPos.check(_data[jjj])) {
|
||||
continue;
|
||||
}
|
||||
if(_data[jjj] == '>') {
|
||||
@ -363,44 +357,44 @@ bool exml::Element::SubParse(const etk::UString& _data, int32_t& _pos, bool _cas
|
||||
}
|
||||
}
|
||||
if (_data[iii+white+1] == '>') {
|
||||
// end of something ==> this is really bad
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find '>' chars ==> invalide XML");
|
||||
// end of something == > this is really bad
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find '>' chars == > invalide XML");
|
||||
return false;
|
||||
}
|
||||
|
||||
if( true == CheckAvaillable(_data[iii+white+1], true) ) {
|
||||
if( true == checkAvaillable(_data[iii+white+1], true) ) {
|
||||
++tmpPos;
|
||||
//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) ) {
|
||||
// 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;
|
||||
}
|
||||
tmpPos.Check(_data[jjj]);
|
||||
tmpPos.check(_data[jjj]);
|
||||
}
|
||||
etk::UString tmpname = _data.Extract(iii+white+1, endPosName+1);
|
||||
if (true==_caseSensitive) {
|
||||
tmpname.Lower();
|
||||
etk::UString tmpname = _data.extract(iii+white+1, endPosName+1);
|
||||
if (true == _caseSensitive) {
|
||||
tmpname.lower();
|
||||
}
|
||||
//EXML_INFO("find node named : '" << tmpname << "'");
|
||||
// find text:
|
||||
exml::Element* element = new exml::Element(tmpname);
|
||||
if (NULL==element) {
|
||||
if (NULL == element) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = endPosName+1;
|
||||
_filePos += tmpPos;
|
||||
if (false==element->IParse(_data, _pos, _caseSensitive, _filePos, _doc)) {
|
||||
if (false == element->iParse(_data, _pos, _caseSensitive, _filePos, _doc)) {
|
||||
delete(element);
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listSub.PushBack(element);
|
||||
m_listSub.pushBack(element);
|
||||
continue;
|
||||
}
|
||||
_filePos+=tmpPos;
|
||||
@ -409,7 +403,7 @@ bool exml::Element::SubParse(const etk::UString& _data, int32_t& _pos, bool _cas
|
||||
return false;
|
||||
} else {
|
||||
if (_data[iii] == '>') {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find elemement '>' ==> no reason to be here ...");
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find elemement '>' == > no reason to be here ...");
|
||||
return false;
|
||||
}
|
||||
// might to be data text ...
|
||||
@ -417,22 +411,22 @@ bool exml::Element::SubParse(const etk::UString& _data, int32_t& _pos, bool _cas
|
||||
|| _data[iii] == ' '
|
||||
|| _data[iii] == '\t'
|
||||
|| _data[iii] == '\r') {
|
||||
// empty spaces ==> nothing to do ....
|
||||
// empty spaces == > nothing to do ....
|
||||
} else {
|
||||
// find data ==> parse it...
|
||||
// find data == > parse it...
|
||||
exml::Text* text = new exml::Text();
|
||||
if (NULL==text) {
|
||||
if (NULL == text) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = iii;
|
||||
_filePos += tmpPos;
|
||||
if (false==text->IParse(_data, _pos, _caseSensitive, _filePos, _doc)) {
|
||||
if (false == text->iParse(_data, _pos, _caseSensitive, _filePos, _doc)) {
|
||||
delete(text);
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listSub.PushBack(text);
|
||||
m_listSub.pushBack(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -443,26 +437,26 @@ bool exml::Element::SubParse(const etk::UString& _data, int32_t& _pos, bool _cas
|
||||
return false;
|
||||
}
|
||||
|
||||
bool exml::Element::IParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc)
|
||||
bool exml::Element::iParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc)
|
||||
{
|
||||
EXML_PARSE_ELEMENT("start parse : 'element' named='" << m_value << "'");
|
||||
// note : When start parsing the upper element must have set the value of the element and set the position after this one
|
||||
m_pos=_filePos;
|
||||
// find a normal node ...
|
||||
for (int32_t iii=_pos; iii<_data.Size(); iii++) {
|
||||
_filePos.Check(_data[iii]);
|
||||
for (int32_t iii=_pos; iii<_data.size(); iii++) {
|
||||
_filePos.check(_data[iii]);
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
DrawElementParsed(_data[iii], _filePos);
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if(_data[iii] == '>') {
|
||||
// we find the end ...
|
||||
_pos = iii+1;
|
||||
return exml::Element::SubParse(_data, _pos, _caseSensitive, _filePos, _doc, false);
|
||||
return exml::Element::subParse(_data, _pos, _caseSensitive, _filePos, _doc, false);
|
||||
}
|
||||
if (_data[iii] == '/') {
|
||||
// standalone node or error...
|
||||
if (iii+1>=_data.Size()) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find end of files ... ==> bad case");
|
||||
if (iii+1>=_data.size()) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find end of files ... == > bad case");
|
||||
return false;
|
||||
}
|
||||
// TODO : Can have white spaces ....
|
||||
@ -474,41 +468,41 @@ bool exml::Element::IParse(const etk::UString& _data, int32_t& _pos, bool _caseS
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Find / without > char ...");
|
||||
return false;
|
||||
}
|
||||
if (true == CheckAvaillable(_data[iii], true)) {
|
||||
// we find an attibute ==> create a new and parse it :
|
||||
if (true == checkAvaillable(_data[iii], true)) {
|
||||
// we find an attibute == > create a new and parse it :
|
||||
exml::Attribute* attribute = new exml::Attribute();
|
||||
if (NULL==attribute) {
|
||||
if (NULL == attribute) {
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Allocation error ...");
|
||||
return false;
|
||||
}
|
||||
_pos = iii;
|
||||
if (false==attribute->IParse(_data, _pos, _caseSensitive, _filePos, _doc)) {
|
||||
if (false == attribute->iParse(_data, _pos, _caseSensitive, _filePos, _doc)) {
|
||||
delete(attribute);
|
||||
return false;
|
||||
}
|
||||
iii = _pos;
|
||||
m_listAttribute.PushBack(attribute);
|
||||
m_listAttribute.pushBack(attribute);
|
||||
continue;
|
||||
}
|
||||
if (false==_data[iii].IsWhiteChar()) {
|
||||
if (false == _data[iii].isWhiteChar()) {
|
||||
CREATE_ERROR(_doc, _data, iii, _filePos, etk::UString("Find an unknow element : '") + _data[iii] + "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, etk::UString("Unexpecting end of parsing exml::Element : '") + m_value + "' ==> check if the '/>' is set or the end of element");
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, etk::UString("Unexpecting end of parsing exml::Element : '") + m_value + "' == > check if the '/>' is set or the end of element");
|
||||
return false;
|
||||
}
|
||||
|
||||
void exml::Element::Clear(void)
|
||||
void exml::Element::clear(void)
|
||||
{
|
||||
exml::AttributeList::Clear();
|
||||
for (int32_t iii=0; iii<m_listSub.Size(); iii++) {
|
||||
exml::AttributeList::clear();
|
||||
for (int32_t iii=0; iii<m_listSub.size(); iii++) {
|
||||
if (NULL!=m_listSub[iii]) {
|
||||
delete(m_listSub[iii]);
|
||||
m_listSub[iii]=NULL;
|
||||
}
|
||||
}
|
||||
m_listSub.Clear();
|
||||
m_listSub.clear();
|
||||
}
|
||||
|
||||
|
||||
|
@ -35,57 +35,57 @@ namespace exml
|
||||
etk::Vector<exml::Node*> m_listSub;
|
||||
public:
|
||||
/**
|
||||
* @brief Get the number of sub element in the node (can be exml::Comment ; exml::Element ; exml::Text :exml::Declaration).
|
||||
* @brief get the number of sub element in the node (can be exml::Comment ; exml::Element ; exml::Text :exml::Declaration).
|
||||
* @return a number >=0.
|
||||
*/
|
||||
int32_t Size(void) const { return m_listSub.Size(); };
|
||||
int32_t size(void) const { return m_listSub.size(); };
|
||||
/**
|
||||
* @brief Add a node at the element (not exml::Attribute (move in the attribute automaticly).
|
||||
* @brief add a node at the element (not exml::Attribute (move in the attribute automaticly).
|
||||
* @param[in] _node Pointer of the node to add.
|
||||
*/
|
||||
void Append(Node* _node);
|
||||
void append(Node* _node);
|
||||
/**
|
||||
* @brief Get the type of the element id.
|
||||
* @brief get the type of the element id.
|
||||
* @param[in] _id Id of the element.
|
||||
* @return the Current type of the element or exml::typeUnknow.
|
||||
*/
|
||||
nodeType_te GetType(int32_t _id);
|
||||
const nodeType_te GetType(int32_t _id) const;
|
||||
nodeType_te getType(int32_t _id);
|
||||
const nodeType_te getType(int32_t _id) const;
|
||||
/**
|
||||
* @brief Get the Node pointer of the element id.
|
||||
* @brief get the Node pointer of the element id.
|
||||
* @param[in] _id Id of the element.
|
||||
* @return Pointer on node.
|
||||
*/
|
||||
Node* GetNode(int32_t _id);
|
||||
const Node* GetNode(int32_t _id) const;
|
||||
Node* getNode(int32_t _id);
|
||||
const Node* getNode(int32_t _id) const;
|
||||
/**
|
||||
* @brief Get the element casted in Element (if the node is not an element return NULL).
|
||||
* @brief get the element casted in Element (if the node is not an element return NULL).
|
||||
* @param[in] _id Id of the element.
|
||||
* @return Pointer on the element or NULL.
|
||||
*/
|
||||
Element* GetElement(int32_t _id);
|
||||
const Element* GetElement(int32_t _id) const;
|
||||
Element* getElement(int32_t _id);
|
||||
const Element* getElement(int32_t _id) const;
|
||||
/**
|
||||
* @brief Get an element with his name (work only with exml::Element)
|
||||
* @brief get an element with his name (work only with exml::Element)
|
||||
* @param[in] _name Name of the element that is requested
|
||||
* @return Pointer on the element or NULL.
|
||||
*/
|
||||
Element* GetNamed(const etk::UString& _name);
|
||||
const Element* GetNamed(const etk::UString& _name) const;
|
||||
Element* getNamed(const etk::UString& _name);
|
||||
const Element* getNamed(const etk::UString& _name) const;
|
||||
/**
|
||||
* @brief Get the internal data of the element (if the element has some sub node thay are converted in xml string ==> like this it is not needed to use <![CDATA[...]]>
|
||||
* @brief get the internal data of the element (if the element has some sub node thay are converted in xml string == > like this it is not needed to use <![CDATA[...]]>
|
||||
* @return the curent data string.
|
||||
*/
|
||||
etk::UString GetText(void);
|
||||
etk::UString getText(void);
|
||||
protected:
|
||||
bool SubParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc, bool _mainNode=false);
|
||||
bool subParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc, bool _mainNode=false);
|
||||
public: // herited function:
|
||||
virtual nodeType_te GetType(void) const { return typeElement; };
|
||||
virtual bool IParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc);
|
||||
virtual bool IGenerate(etk::UString& _data, int32_t _indent) const;
|
||||
virtual exml::Element* ToElement(void) { return this; };
|
||||
virtual const exml::Element* ToElement(void) const { return this; };
|
||||
virtual void Clear(void);
|
||||
virtual nodeType_te getType(void) const { return typeElement; };
|
||||
virtual bool iParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc);
|
||||
virtual bool iGenerate(etk::UString& _data, int32_t _indent) const;
|
||||
virtual exml::Element* toElement(void) { return this; };
|
||||
virtual const exml::Element* toElement(void) const { return this; };
|
||||
virtual void clear(void);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -10,46 +10,41 @@
|
||||
#include <exml/debug.h>
|
||||
|
||||
#undef __class__
|
||||
#define __class__ "Node"
|
||||
#define __class__ "Node"
|
||||
|
||||
|
||||
etk::CCout& exml::operator <<(etk::CCout& _os, const exml::filePos& _obj)
|
||||
{
|
||||
etk::CCout& exml::operator <<(etk::CCout& _os, const exml::filePos& _obj) {
|
||||
_os << "(l=";
|
||||
_os << _obj.GetLine();
|
||||
_os << _obj.getLine();
|
||||
_os << ",c=";
|
||||
_os << _obj.GetCol();
|
||||
_os << _obj.getCol();
|
||||
_os << ")";
|
||||
return _os;
|
||||
}
|
||||
|
||||
exml::Node::Node(const etk::UString& _value) :
|
||||
m_pos(0,0),
|
||||
m_value(_value)
|
||||
{
|
||||
m_pos(0,0),
|
||||
m_value(_value) {
|
||||
// nothing to do.
|
||||
}
|
||||
|
||||
void exml::Node::AddIndent(etk::UString& _data, int32_t _indent) const
|
||||
{
|
||||
void exml::Node::addIndent(etk::UString& _data, int32_t _indent) const {
|
||||
for (int32_t iii=0; iii<_indent; iii++) {
|
||||
_data+="\t";
|
||||
}
|
||||
}
|
||||
|
||||
void exml::Node::DrawElementParsed(const etk::UniChar& _val, const exml::filePos& _filePos) const
|
||||
{
|
||||
if (_val=='\n') {
|
||||
EXML_DEBUG(_filePos << " Parse '\\n'");
|
||||
} else if (_val=='\t') {
|
||||
EXML_DEBUG(_filePos << " Parse '\\t'");
|
||||
void exml::Node::drawElementParsed(const etk::UniChar& _val, const exml::filePos& _filePos) const {
|
||||
if (_val == '\n') {
|
||||
EXML_DEBUG(_filePos << " parse '\\n'");
|
||||
} else if (_val == '\t') {
|
||||
EXML_DEBUG(_filePos << " parse '\\t'");
|
||||
} else {
|
||||
EXML_DEBUG(_filePos << " Parse '" << _val << "'");
|
||||
EXML_DEBUG(_filePos << " parse '" << _val << "'");
|
||||
}
|
||||
}
|
||||
|
||||
bool exml::Node::CheckAvaillable(const etk::UniChar& _val, bool _firstChar) const
|
||||
{
|
||||
bool exml::Node::checkAvaillable(const etk::UniChar& _val, bool _firstChar) const {
|
||||
if( _val == '!'
|
||||
|| _val == '"'
|
||||
|| _val == '#'
|
||||
@ -96,13 +91,12 @@ bool exml::Node::CheckAvaillable(const etk::UniChar& _val, bool _firstChar) cons
|
||||
}
|
||||
|
||||
|
||||
int32_t exml::Node::CountWhiteChar(const etk::UString& _data, int32_t _pos, exml::filePos& _filePos) const
|
||||
{
|
||||
_filePos.Clear();
|
||||
int32_t exml::Node::countWhiteChar(const etk::UString& _data, int32_t _pos, exml::filePos& _filePos) const {
|
||||
_filePos.clear();
|
||||
int32_t white=0;
|
||||
for (int32_t iii=_pos; iii<_data.Size(); iii++) {
|
||||
_filePos.Check(_data[iii]);
|
||||
if(true == _data[iii].IsWhiteChar()) {
|
||||
for (int32_t iii=_pos; iii<_data.size(); iii++) {
|
||||
_filePos.check(_data[iii]);
|
||||
if(true == _data[iii].isWhiteChar()) {
|
||||
white++;
|
||||
} else {
|
||||
break;
|
||||
@ -112,8 +106,7 @@ int32_t exml::Node::CountWhiteChar(const etk::UString& _data, int32_t _pos, exml
|
||||
return white;
|
||||
}
|
||||
|
||||
void exml::Node::Clear(void)
|
||||
{
|
||||
void exml::Node::clear(void) {
|
||||
m_value="";
|
||||
m_pos.Clear();
|
||||
m_pos.clear();
|
||||
}
|
||||
|
118
exml/Node.h
118
exml/Node.h
@ -56,9 +56,8 @@ namespace exml
|
||||
~filePos(void) { };
|
||||
filePos& operator ++(void) { m_col++; return *this; };
|
||||
filePos& operator --(void) { m_col--; if(m_col<0) { m_col=0;} return *this; };
|
||||
const filePos& operator +=(const filePos& _obj)
|
||||
{
|
||||
if (_obj.m_line==0) {
|
||||
const filePos& operator +=(const filePos& _obj) {
|
||||
if (_obj.m_line == 0) {
|
||||
m_col += _obj.m_col;
|
||||
} else {
|
||||
m_col = _obj.m_col;
|
||||
@ -66,39 +65,34 @@ namespace exml
|
||||
}
|
||||
return *this;
|
||||
};
|
||||
const filePos& operator +=(int32_t _col)
|
||||
{
|
||||
const filePos& operator +=(int32_t _col) {
|
||||
m_col += _col;
|
||||
return *this;
|
||||
};
|
||||
const filePos& operator= (const filePos& _obj )
|
||||
{
|
||||
const filePos& operator= (const filePos& _obj ) {
|
||||
m_col = _obj.m_col;
|
||||
m_line = _obj.m_line;
|
||||
return *this;
|
||||
}
|
||||
void NewLine(void) { m_col=0; m_line++; };
|
||||
bool Check(const etk::UniChar& _val)
|
||||
{
|
||||
void newLine(void) { m_col=0; m_line++; };
|
||||
bool check(const etk::UniChar& _val) {
|
||||
m_col++;
|
||||
if (_val=='\n') {
|
||||
NewLine();
|
||||
if (_val == '\n') {
|
||||
newLine();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void Set(int32_t _line, int32_t _col)
|
||||
{
|
||||
void set(int32_t _line, int32_t _col) {
|
||||
m_col = _col;
|
||||
m_line = _line;
|
||||
}
|
||||
void Clear(void)
|
||||
{
|
||||
void clear(void) {
|
||||
m_col = 0;
|
||||
m_line = 0;
|
||||
}
|
||||
int32_t GetCol(void) const { return m_col; };
|
||||
int32_t GetLine(void) const { return m_line; };
|
||||
int32_t getCol(void) const { return m_col; };
|
||||
int32_t getLine(void) const { return m_line; };
|
||||
};
|
||||
etk::CCout& operator <<(etk::CCout& _os, const filePos& _obj);
|
||||
|
||||
@ -120,66 +114,66 @@ namespace exml
|
||||
virtual ~Node(void) { };
|
||||
public:
|
||||
/**
|
||||
* @brief Parse the Current node [pure VIRUAL]
|
||||
* @brief parse the Current node [pure VIRUAL]
|
||||
* @param[in] _data data string to parse.
|
||||
* @param[in,out] _pos position in the string to start parse, return the position end of parsing.
|
||||
* @param[in] _caseSensitive Request a parsion of element that is not case sensitive (all element is in low case)
|
||||
* @param[in,out] file parsing position (line x col x)
|
||||
* @return false if an error occured.
|
||||
*/
|
||||
virtual bool IParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc) = 0;
|
||||
virtual bool iParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc) = 0;
|
||||
/**
|
||||
* @brief Generate a string with the tree of the xml
|
||||
* @brief generate a string with the tree of the xml
|
||||
* @param[in,out] _data string where to add the elements
|
||||
* @param[in] current indentation of the file
|
||||
* @return false if an error occured.
|
||||
*/
|
||||
virtual bool IGenerate(etk::UString& _data, int32_t _indent) const { return true; };
|
||||
virtual bool iGenerate(etk::UString& _data, int32_t _indent) const { return true; };
|
||||
protected:
|
||||
exml::filePos m_pos; //!< position in the readed file ==> not correct when the file is generated
|
||||
exml::filePos m_pos; //!< position in the readed file == > not correct when the file is generated
|
||||
public:
|
||||
/**
|
||||
* @brief Get the current position where the element is in the file
|
||||
* @brief get the current position where the element is in the file
|
||||
*/
|
||||
const exml::filePos& GetPos(void) { return m_pos; };
|
||||
const exml::filePos& getPos(void) { return m_pos; };
|
||||
protected:
|
||||
etk::UString m_value; //!< value of the node (for element this is the name, for text it is the inside text ...)
|
||||
public:
|
||||
/**
|
||||
* @brief Set the value of the node.
|
||||
* @brief set the value of the node.
|
||||
* @param[in] _value New value of the node.
|
||||
*/
|
||||
virtual void SetValue(etk::UString _value) { m_value = _value; };
|
||||
virtual void setValue(etk::UString _value) { m_value = _value; };
|
||||
/**
|
||||
* @brief Get the current element Value.
|
||||
* @brief get the current element Value.
|
||||
* @return the reference of the string value.
|
||||
*/
|
||||
virtual const etk::UString& GetValue(void) const { return m_value; };
|
||||
virtual const etk::UString& getValue(void) const { return m_value; };
|
||||
public:
|
||||
/**
|
||||
* @brief Get the node type.
|
||||
* @brief get the node type.
|
||||
* @return the type of the Node.
|
||||
*/
|
||||
virtual nodeType_te GetType(void) const { return typeNode; };
|
||||
virtual nodeType_te getType(void) const { return typeNode; };
|
||||
protected:
|
||||
/**
|
||||
* @brief Add indentation of the string input.
|
||||
* @brief add indentation of the string input.
|
||||
* @param[in,out] _data String where the indentation is done.
|
||||
* @param[in] _indent Number of tab to add at the string.
|
||||
*/
|
||||
void AddIndent(etk::UString& _data, int32_t _indent) const;
|
||||
void addIndent(etk::UString& _data, int32_t _indent) const;
|
||||
/**
|
||||
* @brief Display the cuurent element that is curently parse.
|
||||
* @param[in] _val Char that is parsed.
|
||||
* @param[in] _filePos Position of the char in the file.
|
||||
*/
|
||||
void DrawElementParsed(const etk::UniChar& _val, const exml::filePos& _filePos) const;
|
||||
void drawElementParsed(const etk::UniChar& _val, const exml::filePos& _filePos) const;
|
||||
/**
|
||||
* @brief check if an element or attribute is availlable (not : !"#$%&'()*+,/;<=>?@[\]^`{|}~ \n\t\r and for first char : not -.0123456789).
|
||||
* @param[in] _val Value to check the conformity.
|
||||
* @param[in] _firstChar True if the element check is the first char.
|
||||
*/
|
||||
bool CheckAvaillable(const etk::UniChar& _val, bool _firstChar) const;
|
||||
bool checkAvaillable(const etk::UniChar& _val, bool _firstChar) const;
|
||||
/**
|
||||
* @brief count the number of white char in the string from the specify position (stop at the first element that is not a white char)
|
||||
* @param[in] _data Data to parse.
|
||||
@ -187,80 +181,80 @@ namespace exml
|
||||
* @param[out] _filePos new poistion of te file to add.
|
||||
* @return number of white element.
|
||||
*/
|
||||
int32_t CountWhiteChar(const etk::UString& _data, int32_t _pos, exml::filePos& _filePos) const;
|
||||
int32_t countWhiteChar(const etk::UString& _data, int32_t _pos, exml::filePos& _filePos) const;
|
||||
public:
|
||||
/**
|
||||
* @brief Cast the element in a Document if it is possible.
|
||||
* @return pointer on the class or NULL.
|
||||
*/
|
||||
virtual exml::Document* ToDocument(void) { return NULL; };
|
||||
virtual const exml::Document* ToDocument(void) const { return NULL; };
|
||||
virtual exml::Document* toDocument(void) { return NULL; };
|
||||
virtual const exml::Document* toDocument(void) const { return NULL; };
|
||||
/**
|
||||
* @brief Cast the element in a Attribute if it is possible.
|
||||
* @return pointer on the class or NULL.
|
||||
*/
|
||||
virtual exml::Attribute* ToAttribute(void) { return NULL; };
|
||||
virtual const exml::Attribute* ToAttribute(void) const { return NULL; };
|
||||
virtual exml::Attribute* toAttribute(void) { return NULL; };
|
||||
virtual const exml::Attribute* toAttribute(void) const { return NULL; };
|
||||
/**
|
||||
* @brief Cast the element in a Comment if it is possible.
|
||||
* @return pointer on the class or NULL.
|
||||
*/
|
||||
virtual exml::Comment* ToComment(void) { return NULL; };
|
||||
virtual const exml::Comment* ToComment(void) const { return NULL; };
|
||||
virtual exml::Comment* toComment(void) { return NULL; };
|
||||
virtual const exml::Comment* toComment(void) const { return NULL; };
|
||||
/**
|
||||
* @brief Cast the element in a Declaration if it is possible.
|
||||
* @return pointer on the class or NULL.
|
||||
*/
|
||||
virtual exml::Declaration* ToDeclaration(void) { return NULL; };
|
||||
virtual const exml::Declaration* ToDeclaration(void) const { return NULL; };
|
||||
virtual exml::Declaration* toDeclaration(void) { return NULL; };
|
||||
virtual const exml::Declaration* toDeclaration(void) const { return NULL; };
|
||||
/**
|
||||
* @brief Cast the element in a Element if it is possible.
|
||||
* @return pointer on the class or NULL.
|
||||
*/
|
||||
virtual exml::Element* ToElement(void) { return NULL; };
|
||||
virtual const exml::Element* ToElement(void) const { return NULL; };
|
||||
virtual exml::Element* toElement(void) { return NULL; };
|
||||
virtual const exml::Element* toElement(void) const { return NULL; };
|
||||
/**
|
||||
* @brief Cast the element in a Text if it is possible.
|
||||
* @return pointer on the class or NULL.
|
||||
*/
|
||||
virtual exml::Text* ToText(void) { return NULL; };
|
||||
virtual const exml::Text* ToText(void) const{ return NULL; };
|
||||
virtual exml::Text* toText(void) { return NULL; };
|
||||
virtual const exml::Text* toText(void) const{ return NULL; };
|
||||
|
||||
/**
|
||||
* @brief Check if the node is a exml::Document
|
||||
* @brief check if the node is a exml::Document
|
||||
* @return true if the node is a exml::Document
|
||||
*/
|
||||
bool IsDocument(void) const { return GetType()==exml::typeDocument; };
|
||||
bool isDocument(void) const { return getType() == exml::typeDocument; };
|
||||
/**
|
||||
* @brief Check if the node is a exml::Attribute
|
||||
* @brief check if the node is a exml::Attribute
|
||||
* @return true if the node is a exml::Attribute
|
||||
*/
|
||||
bool IsAttribute(void) const { return GetType()==exml::typeAttribute; };
|
||||
bool isAttribute(void) const { return getType() == exml::typeAttribute; };
|
||||
/**
|
||||
* @brief Check if the node is a exml::Comment
|
||||
* @brief check if the node is a exml::Comment
|
||||
* @return true if the node is a exml::Comment
|
||||
*/
|
||||
bool IsComment(void) const { return GetType()==exml::typeComment; };
|
||||
bool isComment(void) const { return getType() == exml::typeComment; };
|
||||
/**
|
||||
* @brief Check if the node is a exml::Declaration
|
||||
* @brief check if the node is a exml::Declaration
|
||||
* @return true if the node is a exml::Declaration
|
||||
*/
|
||||
bool IsDeclaration(void) const { return GetType()==exml::typeDeclaration; };
|
||||
bool isDeclaration(void) const { return getType() == exml::typeDeclaration; };
|
||||
/**
|
||||
* @brief Check if the node is a exml::Element
|
||||
* @brief check if the node is a exml::Element
|
||||
* @return true if the node is a exml::Element
|
||||
*/
|
||||
bool IsElement(void) const { return GetType()==exml::typeElement; };
|
||||
bool isElement(void) const { return getType() == exml::typeElement; };
|
||||
/**
|
||||
* @brief Check if the node is a exml::Text
|
||||
* @brief check if the node is a exml::Text
|
||||
* @return true if the node is a exml::Text
|
||||
*/
|
||||
bool IsText(void) const { return GetType()==exml::typeText; };
|
||||
bool isText(void) const { return getType() == exml::typeText; };
|
||||
|
||||
/**
|
||||
* @brief Clear the Node
|
||||
* @brief clear the Node
|
||||
*/
|
||||
virtual void Clear(void);
|
||||
virtual void clear(void);
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -13,16 +13,14 @@
|
||||
#undef __class__
|
||||
#define __class__ "Text"
|
||||
|
||||
bool exml::Text::IGenerate(etk::UString& _data, int32_t _indent) const
|
||||
{
|
||||
bool exml::Text::iGenerate(etk::UString& _data, int32_t _indent) const {
|
||||
_data += m_value;
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t exml::Text::CountLines(void) const
|
||||
{
|
||||
int32_t exml::Text::countLines(void) const {
|
||||
int32_t count = 1;
|
||||
for (int32_t iii=0; iii<m_value.Size(); iii++) {
|
||||
for (int32_t iii=0; iii<m_value.size(); iii++) {
|
||||
if(m_value[iii] == '\n') {
|
||||
count++;
|
||||
}
|
||||
@ -30,16 +28,15 @@ int32_t exml::Text::CountLines(void) const
|
||||
return count;
|
||||
}
|
||||
|
||||
bool exml::Text::IParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc)
|
||||
{
|
||||
bool exml::Text::iParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc) {
|
||||
EXML_VERBOSE("start parse : 'text'");
|
||||
m_pos = _filePos;
|
||||
// search end of the comment :
|
||||
for (int32_t iii=_pos; iii<_data.Size(); iii++) {
|
||||
for (int32_t iii=_pos; iii<_data.size(); iii++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
DrawElementParsed(_data[iii], _filePos);
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if (_filePos.Check(_data[iii]) == true) {
|
||||
if (_filePos.check(_data[iii]) == true) {
|
||||
continue;
|
||||
}
|
||||
if( _data[iii] == '>'
|
||||
@ -47,34 +44,33 @@ bool exml::Text::IParse(const etk::UString& _data, int32_t& _pos, bool _caseSens
|
||||
// search whitespace :
|
||||
int32_t newEnd=iii;
|
||||
for( int32_t jjj=iii-1; jjj>_pos; jjj--) {
|
||||
if(true==_data[jjj].IsWhiteChar()) {
|
||||
if(true == _data[jjj].isWhiteChar()) {
|
||||
newEnd = jjj;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// find end of value:
|
||||
m_value = _data.Extract(_pos, newEnd);
|
||||
m_value = _data.extract(_pos, newEnd);
|
||||
EXML_VERBOSE(" find text '" << m_value << "'");
|
||||
_pos = iii-1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "Text got end of file without finding end node");
|
||||
_pos = _data.Size();
|
||||
_pos = _data.size();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool exml::TextCDATA::IParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc)
|
||||
{
|
||||
bool exml::TextCDATA::iParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc) {
|
||||
EXML_VERBOSE("start parse : 'text::CDATA'");
|
||||
m_pos = _filePos;
|
||||
// search end of the comment :
|
||||
for (int32_t iii=_pos; iii+2<_data.Size(); iii++) {
|
||||
for (int32_t iii=_pos; iii+2<_data.size(); iii++) {
|
||||
#ifdef ENABLE_DISPLAY_PARSED_ELEMENT
|
||||
DrawElementParsed(_data[iii], _filePos);
|
||||
drawElementParsed(_data[iii], _filePos);
|
||||
#endif
|
||||
if (_filePos.Check(_data[iii]) == true) {
|
||||
if (_filePos.check(_data[iii]) == true) {
|
||||
continue;
|
||||
}
|
||||
if( _data[iii] == ']'
|
||||
@ -82,14 +78,14 @@ bool exml::TextCDATA::IParse(const etk::UString& _data, int32_t& _pos, bool _cas
|
||||
&& _data[iii+2] == '>') {
|
||||
// find end of value:
|
||||
_filePos += 2;
|
||||
m_value = _data.Extract(_pos, iii);
|
||||
m_value = _data.extract(_pos, iii);
|
||||
EXML_VERBOSE(" find text CDATA '" << m_value << "'");
|
||||
_pos = iii+2;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
CREATE_ERROR(_doc, _data, _pos, _filePos, "text CDATA got end of file without finding end node");
|
||||
_pos = _data.Size();
|
||||
_pos = _data.size();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
25
exml/Text.h
25
exml/Text.h
@ -12,10 +12,8 @@
|
||||
#include <exml/Node.h>
|
||||
#include <etk/Vector.h>
|
||||
|
||||
namespace exml
|
||||
{
|
||||
class Text : public Node
|
||||
{
|
||||
namespace exml {
|
||||
class Text : public Node {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
@ -31,19 +29,18 @@ namespace exml
|
||||
*/
|
||||
virtual ~Text(void) { };
|
||||
/**
|
||||
* @brief Count the number of line in the current text
|
||||
* @brief count the number of line in the current text
|
||||
* @return The number of lines
|
||||
*/
|
||||
int32_t CountLines(void) const;
|
||||
int32_t countLines(void) const;
|
||||
public: // herited function:
|
||||
virtual nodeType_te GetType(void) const { return typeText; };
|
||||
virtual bool IParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc);
|
||||
virtual bool IGenerate(etk::UString& _data, int32_t _indent) const;
|
||||
virtual exml::Text* ToText(void) { return this; };
|
||||
virtual const exml::Text* ToText(void) const{ return this; };
|
||||
virtual nodeType_te getType(void) const { return typeText; };
|
||||
virtual bool iParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc);
|
||||
virtual bool iGenerate(etk::UString& _data, int32_t _indent) const;
|
||||
virtual exml::Text* toText(void) { return this; };
|
||||
virtual const exml::Text* toText(void) const{ return this; };
|
||||
};
|
||||
class TextCDATA : public Text
|
||||
{
|
||||
class TextCDATA : public Text {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
@ -54,7 +51,7 @@ namespace exml
|
||||
*/
|
||||
virtual ~TextCDATA(void) { };
|
||||
public: // herited function:
|
||||
virtual bool IParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc);
|
||||
virtual bool iParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, exml::filePos& _filePos, exml::Document& _doc);
|
||||
};
|
||||
};
|
||||
|
||||
|
252
exml/test.cpp
252
exml/test.cpp
@ -12,7 +12,7 @@
|
||||
#include <exml/debug.h>
|
||||
|
||||
#undef __class__
|
||||
#define __class__ "test"
|
||||
#define __class__ "test"
|
||||
|
||||
class testCheck
|
||||
{
|
||||
@ -21,7 +21,7 @@ class testCheck
|
||||
etk::UString m_input;
|
||||
int32_t m_errorPos; // -1 : no error , 1 : parsing error, 2 generation error, 3 comparaison error ????
|
||||
testCheck(void) {};
|
||||
void Set(const etk::UString& _ref, int32_t _pos, const etk::UString& _input)
|
||||
void set(const etk::UString& _ref, int32_t _pos, const etk::UString& _input)
|
||||
{
|
||||
m_ref = _ref;
|
||||
m_input = _input;
|
||||
@ -31,230 +31,230 @@ class testCheck
|
||||
|
||||
etk::Vector<testCheck> l_list;
|
||||
|
||||
void Init(void)
|
||||
void init(void)
|
||||
{
|
||||
etk::UString reference;
|
||||
etk::UString input;
|
||||
testCheck check;
|
||||
|
||||
// ======================================================
|
||||
check.Set("test exml::Element", -2, "");
|
||||
l_list.PushBack(check);
|
||||
// ======================================================
|
||||
// == ====================================================
|
||||
check.set("test exml::Element", -2, "");
|
||||
l_list.pushBack(check);
|
||||
// == ====================================================
|
||||
reference = "<exemple/>\n";
|
||||
check.Set(reference,
|
||||
check.set(reference,
|
||||
-1,
|
||||
"<exemple/>\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set(reference,
|
||||
check.set(reference,
|
||||
-1,
|
||||
"< \t\r exemple/>\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set(reference,
|
||||
check.set(reference,
|
||||
-1,
|
||||
"< \t\r exemple \t\r\r\r\n \t\t />\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set(reference,
|
||||
check.set(reference,
|
||||
1,
|
||||
"< exemple < >\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set(reference,
|
||||
check.set(reference,
|
||||
1,
|
||||
"< exemple / />\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set(reference,
|
||||
check.set(reference,
|
||||
1,
|
||||
"< exemple ? />\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set(reference,
|
||||
check.set(reference,
|
||||
1,
|
||||
"< exemple * />\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set(reference,
|
||||
check.set(reference,
|
||||
1,
|
||||
"< . exemple < />\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set(reference,
|
||||
check.set(reference,
|
||||
1,
|
||||
"<! exemple < />\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set(reference,
|
||||
check.set(reference,
|
||||
1,
|
||||
"<!- exemple < />\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set(reference,
|
||||
check.set(reference,
|
||||
1,
|
||||
"< exemple < />\n");
|
||||
l_list.PushBack(check);
|
||||
check.Set("<exemple--/>\n",
|
||||
l_list.pushBack(check);
|
||||
check.set("<exemple--/>\n",
|
||||
1,
|
||||
"<exemple-->\n");
|
||||
l_list.PushBack(check);
|
||||
check.Set("<exemple/>\n",
|
||||
l_list.pushBack(check);
|
||||
check.set("<exemple/>\n",
|
||||
1,
|
||||
"<exemple>\n</exemple sdfgsdfg>\n");
|
||||
l_list.PushBack(check);
|
||||
// ======================================================
|
||||
check.Set("test element exml::Attribute ", -2, "");
|
||||
l_list.PushBack(check);
|
||||
// ======================================================
|
||||
check.Set("<elementtt attr=\"plop\"/>\n",
|
||||
l_list.pushBack(check);
|
||||
// == ====================================================
|
||||
check.set("test element exml::Attribute ", -2, "");
|
||||
l_list.pushBack(check);
|
||||
// == ====================================================
|
||||
check.set("<elementtt attr=\"plop\"/>\n",
|
||||
-1,
|
||||
"<elementtt attr=\"plop\"/>\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<elementtt attr=\"plop\"/>\n",
|
||||
check.set("<elementtt attr=\"plop\"/>\n",
|
||||
-1,
|
||||
"<elementtt attr=plop/>\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<elementtt attr=\"234345@3452345_.'\"/>\n",
|
||||
check.set("<elementtt attr=\"234345@3452345_.'\"/>\n",
|
||||
-1,
|
||||
"<elementtt attr=234345@3452345_.' />\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<elementtt attr=\"plop\"/>\n",
|
||||
check.set("<elementtt attr=\"plop\"/>\n",
|
||||
-1,
|
||||
"<elementtt attr =\"plop\"/>\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<elementtt attr=\"plop\"/>\n",
|
||||
check.set("<elementtt attr=\"plop\"/>\n",
|
||||
-1,
|
||||
"<elementtt attr= \"plop\"/>\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<elementtt attr=\"plop\"/>\n",
|
||||
check.set("<elementtt attr=\"plop\"/>\n",
|
||||
-1,
|
||||
"<elementtt attr\n=\n\"plop\"/>\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<elementtt attr=\"plop\"/>\n",
|
||||
check.set("<elementtt attr=\"plop\"/>\n",
|
||||
-1,
|
||||
"<elementtt attr=plop/>\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<elementtt attr=\"plop\"/>\n",
|
||||
check.set("<elementtt attr=\"plop\"/>\n",
|
||||
-1,
|
||||
"<elementtt attr \n = \n\t plop/>\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<elementtt attr=\"\"/>\n",
|
||||
check.set("<elementtt attr=\"\"/>\n",
|
||||
-1,
|
||||
"<elementtt attr=\"\"/>\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<elementtt attr=\"\"/>\n",
|
||||
check.set("<elementtt attr=\"\"/>\n",
|
||||
-1,
|
||||
"<elementtt attr=/>\n");
|
||||
l_list.PushBack(check);
|
||||
// ======================================================
|
||||
check.Set("test exml::Declaration", -2, "");
|
||||
l_list.PushBack(check);
|
||||
// ======================================================
|
||||
check.Set("<?testDeclaration?>\n",
|
||||
l_list.pushBack(check);
|
||||
// == ====================================================
|
||||
check.set("test exml::Declaration", -2, "");
|
||||
l_list.pushBack(check);
|
||||
// == ====================================================
|
||||
check.set("<?testDeclaration?>\n",
|
||||
-1,
|
||||
"<?testDeclaration?>\n");
|
||||
l_list.PushBack(check);
|
||||
// ======================================================
|
||||
check.Set("test Declaration exml::Attribute", -2, "");
|
||||
l_list.PushBack(check);
|
||||
// ======================================================
|
||||
check.Set("<?xml attr=\"plop\"?>\n",
|
||||
l_list.pushBack(check);
|
||||
// == ====================================================
|
||||
check.set("test Declaration exml::Attribute", -2, "");
|
||||
l_list.pushBack(check);
|
||||
// == ====================================================
|
||||
check.set("<?xml attr=\"plop\"?>\n",
|
||||
-1,
|
||||
"<?xml attr=\"plop\"?>\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<?xml attr=\"plop\"?>\n",
|
||||
check.set("<?xml attr=\"plop\"?>\n",
|
||||
-1,
|
||||
"<?xml attr=plop?>\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<?xml attr=\"234345@3452345_.'\"?>\n",
|
||||
check.set("<?xml attr=\"234345@3452345_.'\"?>\n",
|
||||
-1,
|
||||
"<?xml attr=234345@3452345_.' ?>\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<?xml attr=\"plop\"?>\n",
|
||||
check.set("<?xml attr=\"plop\"?>\n",
|
||||
-1,
|
||||
"<?xml attr =\"plop\"?>\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<?xml attr=\"plop\"?>\n",
|
||||
check.set("<?xml attr=\"plop\"?>\n",
|
||||
-1,
|
||||
"<?xml attr= \"plop\"?>\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<?xml attr=\"plop\"?>\n",
|
||||
check.set("<?xml attr=\"plop\"?>\n",
|
||||
-1,
|
||||
"<?xml attr\n=\n\"plop\"?>\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<?xml attr=\"plop\"?>\n",
|
||||
check.set("<?xml attr=\"plop\"?>\n",
|
||||
-1,
|
||||
"<?xml attr=plop?>\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<?xml attr=\"plop\"?>\n",
|
||||
check.set("<?xml attr=\"plop\"?>\n",
|
||||
-1,
|
||||
"<?xml attr \n = \n\t plop?>\n");
|
||||
l_list.PushBack(check);
|
||||
// ======================================================
|
||||
check.Set("test exml::Comment", -2, "");
|
||||
l_list.PushBack(check);
|
||||
// ======================================================
|
||||
check.Set("<!--exemple-->\n",
|
||||
l_list.pushBack(check);
|
||||
// == ====================================================
|
||||
check.set("test exml::Comment", -2, "");
|
||||
l_list.pushBack(check);
|
||||
// == ====================================================
|
||||
check.set("<!--exemple-->\n",
|
||||
-1,
|
||||
"<!--exemple-->\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<!--exemple-->\n",
|
||||
check.set("<!--exemple-->\n",
|
||||
-1,
|
||||
"<!-- \t \t\t exemple \n\n\n\t-->\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<!---- exemple-->\n",
|
||||
check.set("<!---- exemple-->\n",
|
||||
-1,
|
||||
"<!-- -- exemple -->\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<!--> exemple-->\n",
|
||||
check.set("<!--> exemple-->\n",
|
||||
-1,
|
||||
"<!--> exemple -->\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<!--exemple-->\n",
|
||||
check.set("<!--exemple-->\n",
|
||||
1,
|
||||
"<!-- ---> exemple -->\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<!--exemple-->\n",
|
||||
check.set("<!--exemple-->\n",
|
||||
1,
|
||||
"<!-- ssdfgdfg >\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<!---->\n",
|
||||
check.set("<!---->\n",
|
||||
-1,
|
||||
"<!---->\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("<!--<.:!*%^$0945- '(- &<<< >>> '& ( '( '-' <elementPouris>-->\n",
|
||||
check.set("<!--<.:!*%^$0945- '(- &<<< >>> '& ( '( '-' <elementPouris>-->\n",
|
||||
-1,
|
||||
"<!-- <.:!*%^$0945- '(- &<<< >>> '& ( '( '-' <elementPouris> -->\n");
|
||||
l_list.PushBack(check);
|
||||
// ======================================================
|
||||
check.Set("test all", -2, "");
|
||||
l_list.PushBack(check);
|
||||
// ======================================================
|
||||
l_list.pushBack(check);
|
||||
// == ====================================================
|
||||
check.set("test all", -2, "");
|
||||
l_list.pushBack(check);
|
||||
// == ====================================================
|
||||
reference= "<exemple>\n"
|
||||
" <ex2 ploppp-plpl:erer=\"dfsdfsdfsdf\" lkmjmlk=\"156235\" sdfsdf=\"456321\"/>\n"
|
||||
" <exlkjl-_dsfg./>\n"
|
||||
@ -267,10 +267,10 @@ void Init(void)
|
||||
" Text example ...\n"
|
||||
" </ex2>\n"
|
||||
"</exemple>\n";
|
||||
check.Set(reference, -1, input);
|
||||
l_list.PushBack(check);
|
||||
check.set(reference, -1, input);
|
||||
l_list.pushBack(check);
|
||||
// ------------------------------------------------------
|
||||
check.Set("", 1,
|
||||
check.set("", 1,
|
||||
"< exemple\n >\n"
|
||||
" <ex2 ploppp-plpl:erer=\"dfsdfsdfsdf\" lkmjmlk=\"156235\" sdfsdf=456321 />\n"
|
||||
" <exlkjl-_dsfg./> >\n"
|
||||
@ -278,19 +278,19 @@ void Init(void)
|
||||
" Text example ...\n"
|
||||
" </ex2>\n"
|
||||
"</exemple>\n");
|
||||
l_list.PushBack(check);
|
||||
l_list.pushBack(check);
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
GeneralDebugSetLevel(etk::LOG_LEVEL_VERBOSE);
|
||||
debug::setGeneralLevel(etk::LOG_LEVEL_VERBOSE);
|
||||
Init();
|
||||
int32_t countError = 0;
|
||||
int32_t countSeparator = 0;
|
||||
int32_t sectionID = 0;
|
||||
for (int32_t iii=0 ; iii<l_list.Size() ; iii++) {
|
||||
for (int32_t iii=0 ; iii<l_list.size() ; iii++) {
|
||||
int32_t jjj= iii-countSeparator+1;
|
||||
if (l_list[iii].m_errorPos==-2) {
|
||||
if (l_list[iii].m_errorPos == -2) {
|
||||
countSeparator++;
|
||||
sectionID = 0;
|
||||
EXML_INFO("-------------------------------------------------------------");
|
||||
@ -302,8 +302,8 @@ int main(int argc, const char *argv[])
|
||||
exml::Document doc;
|
||||
etk::UString out("");
|
||||
//EXML_DEBUG("parse : \n" << l_list[iii].m_input);
|
||||
if (false==doc.Parse(l_list[iii].m_input)) {
|
||||
if (l_list[iii].m_errorPos==1) {
|
||||
if (false == doc.parse(l_list[iii].m_input)) {
|
||||
if (l_list[iii].m_errorPos == 1) {
|
||||
EXML_INFO("[TEST] " << sectionID << ":" << jjj << " { OK } Parsing in error (correct result)");
|
||||
} else {
|
||||
EXML_ERROR("[TEST] " << sectionID << ":" << jjj << " {ERROR } Parsing might be OK");
|
||||
@ -312,30 +312,30 @@ int main(int argc, const char *argv[])
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (l_list[iii].m_errorPos==1) {
|
||||
if (l_list[iii].m_errorPos == 1) {
|
||||
EXML_ERROR("[TEST] " << sectionID << ":" << jjj << " {ERROR } Parsing might be in error ...");
|
||||
EXML_ERROR("parse : \n" << l_list[iii].m_input);
|
||||
doc.Display();
|
||||
doc.display();
|
||||
countError++;
|
||||
continue;
|
||||
}
|
||||
if (false == doc.Generate(out)) {
|
||||
if (l_list[iii].m_errorPos==2) {
|
||||
if (false == doc.generate(out)) {
|
||||
if (l_list[iii].m_errorPos == 2) {
|
||||
EXML_INFO("[TEST] " << sectionID << ":" << jjj << " { OK } generate in error (correct result)");
|
||||
} else {
|
||||
EXML_ERROR("[TEST] " << sectionID << ":" << jjj << " {ERROR } Generate output might be OK");
|
||||
EXML_ERROR("[TEST] " << sectionID << ":" << jjj << " {ERROR } generate output might be OK");
|
||||
EXML_ERROR("generate : \n" << out);
|
||||
countError++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (l_list[iii].m_errorPos==2) {
|
||||
if (l_list[iii].m_errorPos == 2) {
|
||||
EXML_ERROR("[TEST] " << sectionID << ":" << jjj << " {ERROR } Generating might be in error ...");
|
||||
countError++;
|
||||
continue;
|
||||
}
|
||||
if (l_list[iii].m_ref != out) {
|
||||
if (l_list[iii].m_errorPos==3) {
|
||||
if (l_list[iii].m_errorPos == 3) {
|
||||
EXML_INFO("[TEST] " << sectionID << ":" << jjj << " { OK } Result in error (normal case)");
|
||||
} else {
|
||||
EXML_ERROR("[TEST] " << sectionID << ":" << jjj << " {ERROR } different output");
|
||||
@ -345,7 +345,7 @@ int main(int argc, const char *argv[])
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (l_list[iii].m_errorPos==3) {
|
||||
if (l_list[iii].m_errorPos == 3) {
|
||||
EXML_ERROR("[TEST] " << sectionID << ":" << jjj << " {ERROR} checking result might be in error...");
|
||||
EXML_ERROR("generate : \n" << out);
|
||||
EXML_ERROR("reference : \n" << l_list[iii].m_ref);
|
||||
@ -355,9 +355,9 @@ int main(int argc, const char *argv[])
|
||||
EXML_INFO("[TEST] " << sectionID << ":" << jjj << " { OK }");
|
||||
}
|
||||
if (countError>0) {
|
||||
EXML_ERROR("[TEST] produce " << countError << " error on " << l_list.Size()-countSeparator << " test");
|
||||
EXML_ERROR("[TEST] produce " << countError << " error on " << l_list.size()-countSeparator << " test");
|
||||
} else {
|
||||
EXML_INFO("[TEST] produce " << countError << " error on " << l_list.Size()-countSeparator << " test");
|
||||
EXML_INFO("[TEST] produce " << countError << " error on " << l_list.size()-countSeparator << " test");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -12,9 +12,8 @@
|
||||
#include <exml/Node.h>
|
||||
#include <exml/Document.h>
|
||||
|
||||
namespace exml
|
||||
{
|
||||
bool Test(void);
|
||||
namespace exml {
|
||||
bool test(void);
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user