diff --git a/exml/Attribute.cpp b/exml/Attribute.cpp index d36c321..be9ddbd 100644 --- a/exml/Attribute.cpp +++ b/exml/Attribute.cpp @@ -19,7 +19,6 @@ exml::Attribute::Attribute(const etk::UString& _name, const etk::UString& _value } - bool exml::Attribute::Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos) { EXML_VERBOSE("start parse : 'attribute'"); @@ -43,7 +42,9 @@ bool exml::Attribute::Parse(const etk::UString& _data, int32_t& _pos, bool _case } } m_name = _data.Extract(_pos, lastElementName+1); - + if (true==_caseSensitive) { + m_name.Lower(); + } if (lastElementName+1>=_data.Size()) { EXML_ERROR(" parse an xml end with an attribute parsing..."); return false; @@ -115,4 +116,12 @@ bool exml::Attribute::Generate(etk::UString& _data, int32_t _indent) const _data += m_value; _data += "\""; return true; -} \ No newline at end of file +} + + + +void exml::Attribute::Clear(void) +{ + m_name=""; +} + diff --git a/exml/Attribute.h b/exml/Attribute.h index b5430d6..eadd247 100644 --- a/exml/Attribute.h +++ b/exml/Attribute.h @@ -17,19 +17,40 @@ namespace exml class Attribute : public Node { public: + /** + * @brief Constructor + */ Attribute(void) { }; + /** + * @brief Constructor + * @param[in] _name Name of the attribute. + * @param[in] _value Value of the attribute. + */ Attribute(const etk::UString& _name, const etk::UString& _value); + /** + * @brief Destructor + */ virtual ~Attribute(void) { }; - virtual nodeType_te GetType(void) const { return exml::typeAttribute; }; - virtual bool Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos); - virtual bool Generate(etk::UString& _data, int32_t _indent) const; protected: etk::UString m_name; public: + /** + * @brief Set the name of the attribute + * @param[in] _name New name of the attribute + */ virtual void SetName(etk::UString _name) { m_name = _name; }; + /** + * @brief Get the current name of the Attribute + * @return String of the attribute + */ virtual const etk::UString& GetName(void) const { return m_name; }; + public: // herited function: + virtual nodeType_te GetType(void) const { return exml::typeAttribute; }; + virtual bool Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos); + virtual bool Generate(etk::UString& _data, int32_t _indent) const; virtual exml::Attribute* ToAttribute(void) { return this; }; virtual const exml::Attribute* ToAttribute(void) const { return this; }; + virtual void Clear(void); }; }; diff --git a/exml/AttributeList.cpp b/exml/AttributeList.cpp index 350ba6f..70675ad 100644 --- a/exml/AttributeList.cpp +++ b/exml/AttributeList.cpp @@ -12,6 +12,17 @@ #undef __class__ #define __class__ "AttributeList" +exml::AttributeList::~AttributeList(void) +{ + for (int32_t iii=0; iiim_listAttribute.Size()) { @@ -28,19 +39,19 @@ const exml::Attribute* exml::AttributeList::GetAttr(int32_t _id) const return m_listAttribute[_id]; } -void exml::AttributeList::AppendAttribute(exml::Attribute* _node) +void exml::AttributeList::AppendAttribute(exml::Attribute* _attr) { - if (_node == NULL) { + if (_attr == NULL) { EXML_ERROR("Try to set an empty node"); return; } for (int32_t iii=0; iiiGetName() == _name) { + return true; + } + } + return false; +} + void exml::AttributeList::SetAttribute(const etk::UString& _name, const etk::UString& _value) { // check if attribute already det : @@ -85,3 +110,17 @@ bool exml::AttributeList::Generate(etk::UString& _data, int32_t _indent) const } return true; } + +void exml::AttributeList::Clear(void) +{ + exml::Node::Clear(); + for (int32_t iii=0; iii m_listAttribute; + etk::Vector m_listAttribute; //!< list of all attribute public: + /** + * @brief Get the number of attribute in the Node + * @return Nulber of attribute >=0 + */ int32_t SizeAttribute(void) const { return m_listAttribute.Size(); }; - void AppendAttribute(Attribute* _node); + /** + * @brief Add attribute on the List + * @param[in] _attr Pointer on the attribute + */ + void AppendAttribute(exml::Attribute* _attr); + /** + * @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; + /** + * @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; + /** + * @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; + /** + * @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); - public: - // herited function: + public: // herited function: bool Generate(etk::UString& _data, int32_t _indent) const; + virtual void Clear(void); }; }; diff --git a/exml/Comment.cpp b/exml/Comment.cpp index 31b77f2..bbb9046 100644 --- a/exml/Comment.cpp +++ b/exml/Comment.cpp @@ -16,8 +16,9 @@ bool exml::Comment::Parse(const etk::UString& _data, int32_t& _pos, bool _caseSe { EXML_VERBOSE("start parse : 'comment'"); m_pos = _filePos; + int32_t white = CountWhiteChar(_data, _pos); // search end of the comment : - for (int32_t iii=_pos; iii+2<_data.Size(); iii++) { + for (int32_t iii=_pos+white; iii+2<_data.Size(); iii++) { _filePos += ivec2(1,0); #ifdef ENABLE_DISPLAY_PARSED_ELEMENT DrawElementParsed(_data[iii], _filePos); @@ -29,8 +30,17 @@ bool exml::Comment::Parse(const etk::UString& _data, int32_t& _pos, bool _caseSe if( _data[iii] == '-' && _data[iii+1] == '-' && _data[iii+2] == '>') { + // search whitespace : + int32_t newEnd=iii; + for( int32_t jjj=iii-1; jjj>_pos; jjj--) { + if(true==_data[jjj].IsWhiteChar()) { + newEnd = jjj; + } else { + break; + } + } // find end of value: - m_value = _data.Extract(_pos, iii-1); + m_value = _data.Extract(_pos+white, newEnd); EXML_VERBOSE(" find comment '" << m_value << "'"); _pos = iii+2; return true; diff --git a/exml/Comment.h b/exml/Comment.h index ca32a5e..d63a33d 100644 --- a/exml/Comment.h +++ b/exml/Comment.h @@ -17,8 +17,20 @@ namespace exml class Comment : public Node { public: + /** + * @brief Constructor + */ Comment(void) { }; + /** + * @brief Constructor + * @param[in] _value comment value + */ + Comment(const etk::UString& _value) : exml::Node(_value) { }; + /** + * @brief Destructor + */ virtual ~Comment(void) { }; + public: // herited function: virtual nodeType_te GetType(void) const { return typeAttribute; }; virtual bool Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos); virtual bool Generate(etk::UString& _data, int32_t _indent) const; diff --git a/exml/Declaration.cpp b/exml/Declaration.cpp index dea36a9..9391339 100644 --- a/exml/Declaration.cpp +++ b/exml/Declaration.cpp @@ -19,7 +19,7 @@ */ -exml::Declaration::Declaration(const etk::UString& _version, unicode::charset_te _format, const etk::UString& _standalone) +exml::Declaration::Declaration(const etk::UString& _version, unicode::charset_te _format, bool _standalone) { m_value = "xml"; if (_version.Size()!=0) { @@ -31,8 +31,10 @@ exml::Declaration::Declaration(const etk::UString& _version, unicode::charset_te EXML_ERROR("Actually does not supported other charset than UTF8"); SetAttribute("encoding", "UTF-8"); } - if (_standalone.Size()!=0) { - SetAttribute("standalone", _standalone); + if (_standalone==true) { + SetAttribute("standalone", "true"); + } else { + SetAttribute("standalone", "true"); } } @@ -74,6 +76,22 @@ bool exml::Declaration::Parse(const etk::UString& _data, int32_t& _pos, bool _ca _pos = iii+1; return true; } + 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) { + EXML_ERROR(_filePos << " Allocation error ..."); + return false; + } + _pos = iii; + if (false==attribute->Parse(_data, _pos, _caseSensitive, _filePos)) { + delete(attribute); + return false; + } + iii = _pos; + m_listAttribute.PushBack(attribute); + continue; + } } _pos = _data.Size(); EXML_ERROR("Text got end of file without finding end node"); diff --git a/exml/Declaration.h b/exml/Declaration.h index af7e608..2dba554 100644 --- a/exml/Declaration.h +++ b/exml/Declaration.h @@ -16,10 +16,23 @@ namespace exml class Declaration : public exml::AttributeList { public: + /** + * @brief Constructor + */ Declaration(void) { }; + /** + * @brief Constructor for the generic declaration : + * @param[in] _version Xml version. + * @param[in] _format charset of the XML + * @param[in] _standalone this document is standalone + */ // for xml generic declaration - Declaration(const etk::UString& _version, unicode::charset_te _format, const etk::UString& _standalone); + Declaration(const etk::UString& _version, unicode::charset_te _format=unicode::EDN_CHARSET_UTF8, bool _standalone=true); + /** + * @brief Destructor + */ virtual ~Declaration(void) { }; + public: // herited function: virtual nodeType_te GetType(void) const { return typeAttribute; }; virtual bool Generate(etk::UString& _data, int32_t _indent) const; virtual bool Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos); diff --git a/exml/Document.cpp b/exml/Document.cpp index 76dae7f..c5bb56b 100644 --- a/exml/Document.cpp +++ b/exml/Document.cpp @@ -37,14 +37,14 @@ bool exml::Document::Parse(const etk::UString& _data, int32_t& _pos, bool _caseS EXML_VERBOSE("start parse : 'document'"); m_pos = _filePos; // in this case : no main node ... - SubParse(_data, _pos, _caseSensitive, _filePos, true); - return true; + return SubParse(_data, _pos, _caseSensitive, _filePos, true); } 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 ... m_charset = unicode::EDN_CHARSET_UTF8; ivec2 filePos(0,1); @@ -62,6 +62,7 @@ bool exml::Document::Load(const etk::UString& _file) { // Start loading the XML : EXML_VERBOSE("open file (xml) \"" << _file << "\""); + Clear(); etk::FSNode tmpFile(_file); if (false == tmpFile.Exist()) { EXML_ERROR("File Does not exist : " << _file); diff --git a/exml/Document.h b/exml/Document.h index 81cc303..246d049 100644 --- a/exml/Document.h +++ b/exml/Document.h @@ -18,18 +18,39 @@ namespace exml class Document : public exml::Element { public: + /** + * @brief Constructor + */ Document(void); + /** + * @brief Destructor + */ virtual ~Document(void) { }; - virtual nodeType_te GetType(void) const { return typeDocument; }; private: unicode::charset_te m_charset; public: + /** + * @brief Get the current charset of the Parsing + * @param[in] _charset The new charset + */ virtual void SetCharset(unicode::charset_te _charset) { m_charset = _charset; }; + /** + * @brief Get the current charset of the Parsing + * @return The current charset + */ virtual unicode::charset_te GetCharset(void) const { return m_charset; }; private: - bool m_caseSensitive; + bool m_caseSensitive; // check the case sensitive of the nodes and attribute public: + /** + * @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; }; + /** + * @brief Get the status of case sensitive mode. + * @return true if case sensitive is active + */ virtual bool GetCaseSensitive(void) const { return m_caseSensitive; }; public: /** @@ -60,8 +81,12 @@ namespace exml * @return true : Parsing is OK */ bool Store(const etk::UString& _file); - + /** + * @brief Display the Document on console + */ void Display(void); + public: // herited function: + virtual nodeType_te GetType(void) const { return typeDocument; }; bool Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos); bool Generate(etk::UString& _data, int32_t _indent) const; virtual exml::Document* ToDocument(void) { return this; }; diff --git a/exml/Element.cpp b/exml/Element.cpp index 093cae0..8d2e2f7 100644 --- a/exml/Element.cpp +++ b/exml/Element.cpp @@ -16,6 +16,20 @@ #undef __class__ #define __class__ "Element" + +exml::Element::~Element(void) +{ + for (int32_t iii=0; iiiGetType()==exml::typeAttribute) { + AppendAttribute(_node->ToAttribute()); + return; + } for (int32_t iii=0; iiiSetValue(tmpname); _pos = iii+white+2; _filePos += ivec2(3+white,0); if (false==declaration->Parse(_data, _pos, _caseSensitive, _filePos)) { @@ -281,6 +320,9 @@ bool exml::Element::SubParse(const etk::UString& _data, int32_t& _pos, bool _cas } } 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 ... @@ -327,6 +369,9 @@ bool exml::Element::SubParse(const etk::UString& _data, int32_t& _pos, bool _cas } } 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(); @@ -347,6 +392,9 @@ bool exml::Element::SubParse(const etk::UString& _data, int32_t& _pos, bool _cas continue; } + // here we have an error : + EXML_ERROR(_filePos << " find an ununderstanding element : '" << _data[iii+white+1] << "'"); + return false; } else { if (_data[iii] == '>') { EXML_ERROR(_filePos << " find elemement '>' ==> no reason to be here ..."); @@ -378,7 +426,7 @@ bool exml::Element::SubParse(const etk::UString& _data, int32_t& _pos, bool _cas } } } - return false; + return true; } bool exml::Element::Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos) @@ -403,15 +451,16 @@ bool exml::Element::Parse(const etk::UString& _data, int32_t& _pos, bool _caseSe if (_data[iii] == '/') { // standalone node or error... if (iii+1>=_data.Size()) { - EXML_ERROR(" find end of files ... ==> bad case"); + EXML_ERROR(_filePos << " find end of files ... ==> bad case"); return false; } + // TODO : Can have white spaces .... if (_data[iii+1] == '>') { _pos = iii+1; return true; } // error - EXML_ERROR("find / without > char ..."); + EXML_ERROR(_filePos << "find / without > char ..."); return false; } if (true == CheckAvaillable(_data[iii], true)) { @@ -430,9 +479,24 @@ bool exml::Element::Parse(const etk::UString& _data, int32_t& _pos, bool _caseSe m_listAttribute.PushBack(attribute); continue; } - // TODO : Else ==> if not white ==> create an error ... + if (false==_data[iii].IsWhiteChar()) { + EXML_ERROR(_filePos << " find an unknow element : '" << _data[iii] << "'"); + return false; + } } - - return false; + return true; } +void exml::Element::Clear(void) +{ + exml::AttributeList::Clear(); + for (int32_t iii=0; iii m_listSub; public: + /** + * @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(); }; + /** + * @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); - + /** + * @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; + /** + * @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; + /** + * @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; + /** + * @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; - public: + /** + * @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 + * @return the curent data string. + */ etk::UString GetText(void); - public: - virtual bool Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos); - virtual bool Generate(etk::UString& _data, int32_t _indent) const; protected: bool SubParse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos, bool _mainNode=false); + public: // herited function: + virtual nodeType_te GetType(void) const { return typeElement; }; + virtual bool Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos); + virtual bool Generate(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); }; }; diff --git a/exml/Node.cpp b/exml/Node.cpp index b518d64..10b8a74 100644 --- a/exml/Node.cpp +++ b/exml/Node.cpp @@ -16,7 +16,7 @@ exml::Node::Node(const etk::UString& _value) : m_pos(0,0), m_value(_value) { - + // nothing to do. } void exml::Node::AddIndent(etk::UString& _data, int32_t _indent) const @@ -38,8 +38,6 @@ void exml::Node::DrawElementParsed(const etk::UniChar& _val, const ivec2& _fileP } } - -// !"#$%&'()*+,/;<=>?@[\]^`{|}~ ou une espace et ne peut pas commencer par -. ou un chiffre. bool exml::Node::CheckAvaillable(const etk::UniChar& _val, bool _firstChar) const { if( _val == '!' @@ -87,14 +85,12 @@ bool exml::Node::CheckAvaillable(const etk::UniChar& _val, bool _firstChar) cons return true; } + int32_t exml::Node::CountWhiteChar(const etk::UString& _data, int32_t _pos) const { int32_t white=0; for (int32_t iii=_pos; iii<_data.Size(); iii++) { - if( _data[iii] == ' ' - || _data[iii] == '\t' - || _data[iii] == '\n' - || _data[iii] == '\r') { + if(true == _data[iii].IsWhiteChar()) { white++; } else { break; @@ -103,3 +99,8 @@ int32_t exml::Node::CountWhiteChar(const etk::UString& _data, int32_t _pos) cons return white; } +void exml::Node::Clear(void) +{ + m_value=""; + m_pos.setValue(0,0); +} diff --git a/exml/Node.h b/exml/Node.h index c9be1ac..05d4944 100644 --- a/exml/Node.h +++ b/exml/Node.h @@ -37,52 +37,161 @@ namespace exml class Node { public: + /** + * @brief basic element of a xml structure + */ Node(void) : m_pos(0,0) { }; + /** + * @brief basic element of a xml structure + * @param[in] value of the node + */ Node(const etk::UString& _value); + /** + * @brief destructor + */ virtual ~Node(void) { }; - protected: - void AddIndent(etk::UString& _data, int32_t _indent) const; public: /** - * Parse the sub nodes and current nodes ... + * @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 Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos) = 0; + /** + * @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 Generate(etk::UString& _data, int32_t _indent) const { return true; }; protected: - ivec2 m_pos; // position in the readed file + ivec2 m_pos; //!< position in the readed file ==> not correct when the file is generated public: - const ivec2& Pos(void) { return m_pos; }; + /** + * @brief Get the current position where the element is in the file + */ + const ivec2& GetPos(void) { return m_pos; }; protected: - etk::UString m_value; + 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. + * @param[in] _value New value of the node. + */ virtual void SetValue(etk::UString _value) { m_value = _value; }; + /** + * @brief Get the current element Value. + * @return the reference of the string value. + */ virtual const etk::UString& GetValue(void) const { return m_value; }; public: + /** + * @brief Get the node type. + * @return the type of the Node. + */ virtual nodeType_te GetType(void) const { return typeNode; }; protected: - void DrawElementParsed(const etk::UniChar& _val, const ivec2& _firstChar) const; + /** + * @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; + /** + * @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 ivec2& _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; + /** + * @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. + * @param[in] _pos Start position in the string. + * @return number of white element. + */ int32_t CountWhiteChar(const etk::UString& _data, int32_t _pos) 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; }; + /** + * @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; }; + /** + * @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; }; + /** + * @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; }; + /** + * @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; }; + /** + * @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; }; + /** + * @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; }; + /** + * @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; }; + /** + * @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; }; + /** + * @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; }; + /** + * @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; }; + /** + * @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; }; + + /** + * @brief Clear the Node + */ + virtual void Clear(void); }; }; diff --git a/exml/Text.cpp b/exml/Text.cpp index d7fe474..8f681f4 100644 --- a/exml/Text.cpp +++ b/exml/Text.cpp @@ -48,10 +48,7 @@ bool exml::Text::Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensi // search whitespace : int32_t newEnd=iii; for( int32_t jjj=iii-1; jjj>_pos; jjj--) { - if( _data[jjj] == ' ' - || _data[jjj] == '\n' - || _data[jjj] == '\r' - || _data[jjj] == '\t') { + if(true==_data[jjj].IsWhiteChar()) { newEnd = jjj; } else { break; diff --git a/exml/Text.h b/exml/Text.h index 8f9e343..7ef3e3b 100644 --- a/exml/Text.h +++ b/exml/Text.h @@ -17,22 +17,43 @@ namespace exml class Text : public Node { public: + /** + * @brief Constructor + */ Text(void) { }; - Text(const etk::UString& _data) { m_value=_data; }; + /** + * @brief Constructor + * @param[in] _data String data of the current Text + */ + Text(const etk::UString& _data) : exml::Node(_data) { }; + /** + * @brief Destructor + */ virtual ~Text(void) { }; + /** + * @brief Count the number of line in the current text + * @return The number of lines + */ + int32_t CountLines(void) const; + public: // herited function: virtual nodeType_te GetType(void) const { return typeText; }; virtual bool Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos); virtual bool Generate(etk::UString& _data, int32_t _indent) const; - int32_t CountLines(void) const; virtual exml::Text* ToText(void) { return this; }; virtual const exml::Text* ToText(void) const{ return this; }; }; class TextCDATA : public Text { public: + /** + * @brief Constructor + */ TextCDATA(void) { }; + /** + * @brief Destructor + */ virtual ~TextCDATA(void) { }; - virtual nodeType_te GetType(void) { return typeText; }; + public: // herited function: virtual bool Parse(const etk::UString& _data, int32_t& _pos, bool _caseSensitive, ivec2& _filePos); }; }; diff --git a/exml/exml.h b/exml/exml.h index 16b659e..5f269f0 100644 --- a/exml/exml.h +++ b/exml/exml.h @@ -11,5 +11,6 @@ #include + #endif diff --git a/exml/test.cpp b/exml/test.cpp index c93153b..77870fa 100644 --- a/exml/test.cpp +++ b/exml/test.cpp @@ -8,28 +8,235 @@ #include #include +#include #include #undef __class__ #define __class__ "test" +class testCheck +{ + public: + etk::UString m_ref; + 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) + { + m_ref = _ref; + m_input = _input; + m_errorPos = _pos; + } +}; + +etk::Vector l_list; + +void Init(void) +{ + etk::UString reference; + etk::UString input; + testCheck check; + + // ====================================================== + reference = "\n"; + check.Set(reference, + -1, + "\n"); + l_list.PushBack(check); + // ------------------------------------------------------ + check.Set(reference, + -1, + "< \t\r exemple/>\n"); + l_list.PushBack(check); + // ------------------------------------------------------ + check.Set(reference, + -1, + "< \t\r exemple \t\r\r\r\n \t\t />\n"); + l_list.PushBack(check); + // ------------------------------------------------------ + check.Set(reference, + 1, + "< exemple < >\n"); + l_list.PushBack(check); + // ------------------------------------------------------ + check.Set(reference, + 1, + "< exemple / />\n"); + l_list.PushBack(check); + // ------------------------------------------------------ + check.Set(reference, + 1, + "< exemple ? />\n"); + l_list.PushBack(check); + // ------------------------------------------------------ + check.Set(reference, + 1, + "< exemple * />\n"); + l_list.PushBack(check); + // ------------------------------------------------------ + check.Set(reference, + 1, + "< . exemple < />\n"); + l_list.PushBack(check); + // ------------------------------------------------------ + check.Set(reference, + 1, + "\n"); + l_list.PushBack(check); + // ------------------------------------------------------ + check.Set(reference, + 1, + "\n"); + l_list.PushBack(check); + // ------------------------------------------------------ + check.Set(reference, + 1, + "< exemple < />\n"); + l_list.PushBack(check); + check.Set("\n", + 1, + "\n"); + l_list.PushBack(check); + // ------------------------------------------------------ + // ====================================================== + check.Set("", -2, ""); + l_list.PushBack(check); + // ====================================================== + check.Set("\n", + -1, + "\n"); + l_list.PushBack(check); + // ------------------------------------------------------ + check.Set("\n", + -1, + "\n"); + l_list.PushBack(check); + // ------------------------------------------------------ + check.Set("\n", + -1, + "\n"); + l_list.PushBack(check); + // ------------------------------------------------------ + check.Set(" exemple-->\n", + -1, + " exemple -->\n"); + l_list.PushBack(check); + // ------------------------------------------------------ + check.Set("\n", + 1, + " exemple -->\n"); + l_list.PushBack(check); + // ------------------------------------------------------ + check.Set("\n", + 1, + "\n", + -1, + "\n"); + l_list.PushBack(check); + // ------------------------------------------------------ + check.Set("\n", + -1, + "\n"); + l_list.PushBack(check); + // ====================================================== + check.Set("", -2, ""); + l_list.PushBack(check); + // ====================================================== + reference= "\n" + " \n" + " \n" + " Text example ...\n" + "\n"; + input ="< exemple\n >\n" + " \n" + " \n" + " \n" + " Text example ...\n" + " \n" + "\n"; + check.Set(reference, 1, input); + l_list.PushBack(check); +} + int main(int argc, const char *argv[]) { GeneralDebugSetLevel(etk::LOG_LEVEL_VERBOSE); - exml::Document doc; - etk::UString testString = "" - "< exemple\n >\n" - " \n" - " \n" - " \n" - " Text example ...\n" -// " \n" -// " < < S!! ]]>\n" - " \n" - "\n"; - EXML_DEBUG("start parsing : \n" << testString); - doc.Parse(testString); - doc.Display(); - return false; + Init(); + int32_t countError = 0; + int32_t countSeparator = 0; + int32_t sectionID = 0; + for (int32_t iii=0 ; iii0) { + 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"); + } + return 0; }