/***************************************************************************
                          SIMPLY POWERFUL TOOLKIT (SPTK)
                          CXmlParser.h  -  description
                             -------------------
    begin                : Sun May 22 2003
    based on the code    : Mikko Lahteenmaki <Laza@Flashmail.com>
    copyright            : (C) 2003-2005 by Alexey S.Parshin
    email                : alexeyp@gmail.com
 ***************************************************************************/

/***************************************************************************
   This library is free software; you can redistribute it and/or modify it 
   under the terms of the GNU Library General Public License as published by
   the Free Software Foundation; either version 2 of the License, or (at 
   your option) any later version.

   This library is distributed in the hope that it will be useful, but 
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library
   General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; if not, write to the Free Software Foundation, 
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

   Please report all bugs and problems to "alexeyp@gmail.com"
 ***************************************************************************/

#ifndef _FL_XMLPARSER_H_
#define _FL_XMLPARSER_H_

#include "CXml.h"
#include "CXmlHandler.h"
#include "CXmlTokenizer.h"

class CXmlNode;
class CXmlDoc;

/// @addtogroup XML
/// @{

/// @brief XML parser (internal).
///
/// The parser is non-validating parser. It cannot handle external DTD's at all.
/// Internal DTD's are partially handled, i.e. custom entities are parsed, though
/// parameter entities are not supported. 
/// Parser expands entitied during parsing, so entity reference nodes are not supported either.
/// I.e. cdata/attributes stored to node or send to SAX handler, are already expanded.
class CXmlParser {
   friend class CXmlTokenizer;

public:
   /// Parses new XML/HTML document from stream. throws CXmlException on error.
   /// You can set own tokenizer, e.g. which reads data from net.
   /// @param doc CXmlDoc&, destination XML/HTML document. It's cleared before parse begins.
   /// @param tokenizer CXmlTokenizer &, stream for document data to parse.
   /// @param locator CXmlLocator *, locator for tokenizer. If error occurs, you can get position from here.
   /// @param htmlMode bool, document is parsed in HTML mode, for XML this should be always false.
   static void createDOM(CXmlDoc& doc,CXmlTokenizer &tokenizer, CXmlLocator *locator=0, bool htmlMode=false);

   /// Parses new XML/HTML document from stream. throws CXmlException on error.
   /// @param doc CXmlDoc&, destination XML/HTML document. It's cleared before parse begins.
   /// @param buffer CBuffer&, pointer to data for parse.
   /// @param locator CXmlLocator *, locator for tokenizer. If error occurs, you can get position from here.
   /// @param htmlMode bool, document is parsed in HTML mode, for XML this should be always false.
   static void createDOM(CXmlDoc& doc,const CBuffer& buffer, CXmlLocator *locator=0, bool htmlMode=false);

   /**
    * Parse XML/HTML document in SAX mode. 
    * This is good for large XML documents, where keeping nodes in memory
    * would take too much memory. While parsing document, handler methods are called.
    * @param handler CXmlHandler &, SAX handler to use catch events.
    * @param tokenizer CXmlTokenizer &, stream for document data to parse.
    * @param htmlMode bool, document is parsed in HTML mode, for XML this should be always false.
    * @see CXmlHandler
    */
   static bool createSAX(CXmlHandler &handler, CXmlTokenizer &tokenizer, bool htmlMode=false);

   /**
    * Parse XML/HTML document in SAX mode. 
    * This is good for large XML documents, where keeping nodes in memory
    * would take too much memory. While parsing document, handler methods are called.
    * @param handler CXmlHandler &, SAX handler to use catch events.
    * @param buffer const CBuffer&, pointer to data for parse.
    * @param htmlMode bool, document is parsed in HTML mode, for XML this should be always false.
    * @see CXmlHandler
    */
   static bool createSAX(CXmlHandler &handler, const CBuffer& buffer, bool htmlMode=false);

   /**
    * Sets the SAX event handler. If handler is NULL, SAX events are ignored
    * and nodes are stored to DOM tree.
     * @param handler CXmlHandler *, event handler to set
    */
   void handler(CXmlHandler *handler) { m_eventhandler = handler; }

   /// Returns current SAX event handler, NULL if none specific.
   CXmlHandler *handler() const { return m_eventhandler; }

protected:
   /**
    * Create new parser.
    * @param tokenizer is used as stream tokenizer.
    */
   CXmlParser(CXmlTokenizer &tokenizer);

   /// Parse subnodes until end-of-stream 
   bool parseDocument(CXmlDoc *doc);

   /// Parse doctype declaration 
   bool parseDocType(CXmlDocType *doc);

   /// Parse a node and its subnodes 
   bool parseNode(CXmlDoc *doc, CXmlNode *node);

   /// Parse an XML node attributes to attr 
   bool parseAttributes(CXmlDoc *doc, CXmlAttributes *attr);

   /// Parse a comment (<!-- -->) 
   bool parseComment(CXmlNode *node);

   /// Turn HTML mode on/off
   void htmlMode(bool val) { m_htmlMode = val; }

   /// Return current mode of parser 
   bool htmlMode() const { return m_htmlMode; }

private:

   CXmlTokenizer &tokenizer;         ///< Stream tokenizer
   CXmlHandler   *m_eventhandler;    ///< Event handler pointer

   bool        m_htmlMode;           ///< Html mode parsing flag
   bool        tag_end;              ///< Tag end flag
   int         force_ret;            ///< Force return
   std::string last_block;           ///< Last Block
   std::string parent_name;          ///< Parent name
};

/// @}

#endif
