/***************************************************************************
                           cxml.h  -  description
                             -------------------
    begin                : Sun Jun 9 2002
    copyright            : (C) 2002-2004 by Mathias Küster
    email                : mathen@users.berlios.de
 ***************************************************************************/

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

#ifndef CXML_H
#define CXML_H

/**
  * @author Mathias Küster, Edward Sheldrake (changed API described below)
  *
  * The API was changed so that the rest of dclib
  * and valknut do not use libxml2 functions / objects directly.
  *
  * Instead the CXml object has a current node which is operated on
  * and functions to move to the next node, to it's first child
  * or back to the parent node.
  * There is no longer any xmlNodePtr parameter passing.
  *
  * The only disadvantage of the new API is that there are null
  * pointer checks in each CXml function.
  *
  * Also the API requires a do ... while loop instead of a for loop
  * and Parent() must be called once you have finished parsing or
  * adding the children.
  */

#include <dclib/dcos.h>
#include <dclib/core/cstring.h>

class CIconv;
class CByteArray;

struct _xmlDoc;
struct _xmlNode;

class CXml {

public:
	/** */
	CXml();
	/** */
	~CXml();

	/** */
	CString Name();
	/** */
	CString Content();
	/** */
	CString Prop( const CString & prop );
	/** */
	CString Prop( const char * prop );
	/** */
	bool GetBoolChild();
	/**
	 * Moves to the document's first child node, and returns true if
	 * it is not null.
	 */
	bool DocFirstChild();
	/**
	 * If the next node is not null, moves to it and returns true.
	 * Otherwise returns false.
	 *
	 * Strangely there is no "PreviousNode" function because
	 * dclib / valknut does not need it.
	 */
	bool NextNode();
	/**
	 * Moves the current node to the first child node if there is one.
	 */
	bool FirstChild();
	/**
	 * If the current node's parent is not null, moves to it and
	 * returns true, otherwise returns false.
	 *
	 * This function is used both when reading and writing XML documents.
	 */
	bool Parent();
	/**
	 * Creates a new child node with the given name
	 * which becomes the current node.
	 *
	 * All the NewBoolChild / NewNumericChild / NewStringChild functions
	 * add a new node as a child of the current node.
	 */
	bool StartNewChild( const char * name );
	/** */
	bool NewBoolChild( const char * name, bool b );
	/** */
	bool NewNumericChild( const char * name, const int n );
	/** */
	bool NewNumericChild( const char * name, const unsigned int n );
	/** */
	bool NewNumericChild( const char * name, const long n );
	/** */
	bool NewNumericChild( const char * name, const unsigned long n );
	/** */
	bool NewNumericChild( const char * name, const long long n );
	/** */
	bool NewNumericChild( const char * name, const ulonglong n );
	/** The almost unused create empty parameter was removed */
	bool NewStringChild( const char * name, const CString & s );
	/** The almost unused create empty parameter was removed */
	bool NewStringChild( const char * name, const char * s );
	/** */
	bool NewStringProp( const CString & prop, const CString & value );
	/** */
	bool NewStringProp( const char * prop, const char * value );

	/**
	 * Now both creates a new document
	 * and creates the document node with the given name.
	 */
	bool NewDoc( const char * docnodename );
	/** */
	bool ParseFile( CString name );
	/** */
	bool ParseMemory( const char * s, int size );
	/**
	 * Parses the memory, modifying it if necessary
	 * so that it parses. For XML hublists.
	 */
	bool ParseFixMemory( CByteArray * ba );
	/**
	 * Saves the config file by first writing it to a temp file,
	 * deleting the original, then renaming the temp file back to
	 * the original name.
	 * Returns 1000 if successful or -1 in case of error.
	 * (The libxml2 functions now used do not return the total byte size of the file).
	 */
	int SaveConfigXmlViaTemp( CString name );

	/** */
	CString ToUTF8( const CString & s );
	/** */
	CString FromUtf8( const CString & s );
	/** */
	CString ToUTF8( const char * s );
	/** */
	CString FromUtf8( const char * s );
	/** */
	static CString EscapeSpecials( const CString & s );
	/** */
	static CString UnEscapeSpecials( const CString & s );
	
	/** Must be called once on program startup */
	static void InitParser();
	/** Must be called once on program shutdown */
	static void CleanupParser();
	
	/** */
	static const char * Libxml2CompiledVersion();
	/** */
	static const char * Libxml2RunningVersion();

private:
	/** */
	void FreeDoc();

	/** */
	_xmlDoc * pDoc;
	/** */
	_xmlNode * pNode;
	
	/** Encodes from local to UTF-8 */
	CIconv * pToUTF8;
	/** Encodes from UTF-8 to local */
	CIconv * pFromUTF8;
};

#endif
