/*
    GSK - a library to write servers
    Copyright (C) 2001 Dave Benson

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser 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

    Contact:
        daveb@ffem.org <Dave Benson>
*/

#ifndef __GSK_XML_PARSER_H_
#define __GSK_XML_PARSER_H_


/*
 * To process an xml document, not using the Gtk object system,
 * first you set up a GskXmlParser, by registing "user functions"
 * that are called on <open-tag>, </close-tag> and text-data.
 *
 * then processing proceeds:  input is sent to the parser
 * separately from parsing (the production of tokens and running of callbacks)
 *
 * raw xml data        +------------+
 * ------------------->|GskXmlParser|
 * gsk_xml_parser_feed +------------+       ----->----\
 *                           |             /           \
 *                           |            /             \
 *                           |gsk_xml_parser_try    (call user functions)
 *                           |            \             /
 *                           |             \           /
 *                          \ /             -----<-----
 *                           +
 *                     +-----------+
 *                     |GskXmlToken|
 *                     +-----------+
 *
 * This is a pretty low-level view: usually you'd use GskXmlProcessor
 * to automatically use the registered parameters and so on to parse
 * the document into GtkObjects.
 */



typedef enum
{
  GSK_XML_PARSER_OK,
  GSK_XML_PARSER_TAG_MISMATCH,
  GSK_XML_PARSER_MALFORMED,
  GSK_XML_PARSER_OUT_OF_DATA,
  GSK_XML_PARSER_PREMATURE_EOF,
  GSK_XML_PARSER_EOF,
  GSK_XML_PARSER_INTERNAL
} GskXmlParserStatus;

typedef struct _GskXmlParser GskXmlParser;
#include "gskxmltoken.h"

GskXmlParser       *gsk_xml_parser_new     ();

typedef enum
{
  GSK_XML_PARSER_READ_COMMENTS = (1<<0)
} GskXmlParserFlags;

void                gsk_xml_parser_set_flags(GskXmlParser       *parser,
					     GskXmlParserFlags   flags);
GskXmlParserFlags   gsk_xml_parser_get_flags(GskXmlParser       *parser);

/* feed some data into the parser's buffer. */
void                gsk_xml_parser_feed    (GskXmlParser *parser,
                                            int           length,
                                            const char   *data);

/* parse one token and call the needed callbacks.
 * - if you want the token, pass in a reference to
 *   a pointer:
 *     GskXmlToken *token;
 *     gsk_xml_parser_try (parser, &token);
 *     ...
 *     call gsk_xml_token_unref (token) on non-error returns
 *
 * - if you just want expat-compatibility,
 *   pass in NULL for token_out.
 */
GskXmlParserStatus  gsk_xml_parser_try     (GskXmlParser *parser,
					    GskXmlToken **token_out);

/* indicate that no more data is coming: parser will
 * eventually return GSK_XML_PARSER_EOF.
 * XXX: this isn't necessary.  Just don't allow `OUT_OF_DATA' at
 *      end of document...
 */
void                gsk_xml_parser_set_eof (GskXmlToken  *parser);

void                gsk_xml_parser_destroy (GskXmlParser *parser);

/* --- expat porting --- */
typedef void (*GskXmlStartElementHandler)(gpointer       user_data,
					  const char    *name,
					  const char   **atts);
typedef void (*GskXmlEndElementHandler)  (gpointer       user_data,
					  const char    *name);
/* Note: we NUL-terminate content, but expat does not,
 * so if you wish to work with expat also, you must not assume
 * the NUL!
 */
typedef void (*GskXmlTextHandler)        (gpointer       user_data,
					  const char    *content,
					  int            content_length);
void gsk_xml_parser_set_user_data    (GskXmlParser *parser,
				      gpointer      user_data);
void gsk_xml_parser_set_element_handlers(GskXmlParser *parser,
				         GskXmlStartElementHandler,
				         GskXmlEndElementHandler);
void gsk_xml_parser_set_text_handler (GskXmlParser *parser,
				      GskXmlTextHandler);
void gsk_xml_parser_set_comment_handler (GskXmlParser *parser,
				         GskXmlTextHandler);

void gsk_xml_parser_get_position    (GskXmlParser  *parser,
				     const char   **filename_out,
				     guint         *lineno_out);
void gsk_xml_parser_set_position    (GskXmlParser  *parser,
				     const char    *filename,
				     guint          lineno);
/*
   BUGS: setting the comment_handler to NULL and back can result
   in strangely lost comments, because we don't waste memory storing
   comments unless the handler is non-NULL or the READ_COMMENTS
   flag is raised:

   Moral: if you really want to trap and untrap comments a lot,
   you oughta set the READ_COMMENTS flag!
 */

/* unwritten handlers: StartCdata, EndCdata, 
                       ProcessingInstruction, Default. */

#endif
