xml.h revision 7f1db520ded2b0454dd839fdf9ecae555b3a28fe
/** @file
* VirtualBox XML helper APIs.
*/
/*
* Copyright (C) 2007-2008 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* you can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
#ifndef ___VBox_vboxxml_h
#define ___VBox_vboxxml_h
#include <iprt/cdefs.h>
#include <iprt/cpputils.h>
/* these conflict with numeric_digits<>::min and max */
#undef min
#undef max
#include <iprt/mem.h>
#ifndef IN_RING3
# error "There are no XML APIs available in Ring-0 Context!"
#else /* IN_RING3 */
/** @def IN_VBOXXML_R3
* Used to indicate whether we're inside the same link module as the
* XML Settings File Manipulation API.
*
* @todo should go to a separate common include together with VBOXXML2_CLASS
* once there becomes more than one header in the VBoxXML2 library.
*/
#ifdef DOXYGEN_RUNNING
# define IN_VBOXXML_R3
#endif
/** @def VBOXXML_CLASS
* Class export/import wrapper. */
#ifdef IN_VBOXXML_R3
# define VBOXXML_CLASS DECLEXPORT_CLASS
#else
# define VBOXXML_CLASS DECLIMPORT_CLASS
#endif
/*
* Shut up MSVC complaining that auto_ptr[_ref] template instantiations (as a
* result of private data member declarations of some classes below) need to
* be exported too to in order to be accessible by clients.
*
* The alternative is to instantiate a template before the data member
* declaration with the VBOXXML_CLASS prefix, but the standard disables
* explicit instantiations in a foreign namespace. In other words, a declaration
* like:
*
* template class VBOXXML_CLASS std::auto_ptr <Data>;
*
* right before the member declaration makes MSVC happy too, but this is not a
* valid C++ construct (and G++ spits it out). So, for now we just disable the
* warning and will come back to this problem one day later.
*
* We also disable another warning (4275) saying that a DLL-exported class
* inherits form a non-DLL-exported one (e.g. settings::ENoMemory ->
* std::bad_alloc). I can't get how it can harm yet.
*/
#if defined(_MSC_VER)
#pragma warning (disable:4251)
#pragma warning (disable:4275)
#endif
/* Forwards */
typedef struct _xmlParserInput xmlParserInput;
typedef xmlParserInput *xmlParserInputPtr;
typedef struct _xmlParserCtxt xmlParserCtxt;
typedef xmlParserCtxt *xmlParserCtxtPtr;
typedef struct _xmlError xmlError;
typedef xmlError *xmlErrorPtr;
namespace xml
{
// Exceptions
//////////////////////////////////////////////////////////////////////////////
/**
* Base exception class.
*/
class VBOXXML_CLASS Error : public std::exception
{
public:
Error (const char *aMsg = NULL)
: m (aMsg ? Str::New (aMsg) : NULL) {}
virtual ~Error() throw() {}
void setWhat (const char *aMsg) { m = aMsg ? Str::New (aMsg) : NULL; }
const char *what() const throw() { return m.is_null() ? NULL : m->str; }
private:
/** smart string with support for reference counting */
struct Str
{
size_t ref() { return ++ refs; }
size_t unref() { return -- refs; }
size_t refs;
char str [1];
static Str *New (const char *aStr)
{
Str *that = (Str *) RTMemAllocZ (sizeof (Str) + strlen (aStr));
AssertReturn (that, NULL);
strcpy (that->str, aStr);
return that;
}
void operator delete (void *that, size_t) { RTMemFree (that); }
};
stdx::auto_ref_ptr <Str> m;
};
class VBOXXML_CLASS LogicError : public Error
{
public:
LogicError (const char *aMsg = NULL) : Error (aMsg) {}
LogicError (RT_SRC_POS_DECL);
};
class VBOXXML_CLASS RuntimeError : public Error
{
public:
RuntimeError (const char *aMsg = NULL) : Error (aMsg) {}
};
// Logical errors
//////////////////////////////////////////////////////////////////////////////
class VBOXXML_CLASS ENotImplemented : public LogicError
{
public:
ENotImplemented (const char *aMsg = NULL) : LogicError (aMsg) {}
ENotImplemented (RT_SRC_POS_DECL) : LogicError (RT_SRC_POS_ARGS) {}
};
class VBOXXML_CLASS EInvalidArg : public LogicError
{
public:
EInvalidArg (const char *aMsg = NULL) : LogicError (aMsg) {}
EInvalidArg (RT_SRC_POS_DECL) : LogicError (RT_SRC_POS_ARGS) {}
};
// Runtime errors
//////////////////////////////////////////////////////////////////////////////
class VBOXXML_CLASS ENoMemory : public RuntimeError, public std::bad_alloc
{
public:
ENoMemory (const char *aMsg = NULL) : RuntimeError (aMsg) {}
virtual ~ENoMemory() throw() {}
};
class VBOXXML_CLASS EIPRTFailure : public RuntimeError
{
public:
EIPRTFailure (const char *aMsg = NULL) : RuntimeError (aMsg) {}
EIPRTFailure (int aRC) : mRC (aRC) {}
int rc() const { return mRC; }
private:
int mRC;
};
/**
* The Stream class is a base class for I/O streams.
*/
class VBOXXML_CLASS Stream
{
public:
virtual ~Stream() {}
virtual const char *uri() const = 0;
/**
* Returns the current read/write position in the stream. The returned
* position is a zero-based byte offset from the beginning of the file.
*
* Throws ENotImplemented if this operation is not implemented for the
* given stream.
*/
virtual uint64_t pos() const = 0;
/**
* Sets the current read/write position in the stream.
*
* @param aPos Zero-based byte offset from the beginning of the stream.
*
* Throws ENotImplemented if this operation is not implemented for the
* given stream.
*/
virtual void setPos (uint64_t aPos) = 0;
};
/**
* The Input class represents an input stream.
*
* This input stream is used to read the settings tree from.
* This is an abstract class that must be subclassed in order to fill it with
* useful functionality.
*/
class VBOXXML_CLASS Input : virtual public Stream
{
public:
/**
* Reads from the stream to the supplied buffer.
*
* @param aBuf Buffer to store read data to.
* @param aLen Buffer length.
*
* @return Number of bytes read.
*/
virtual int read (char *aBuf, int aLen) = 0;
};
/**
*
*/
class VBOXXML_CLASS Output : virtual public Stream
{
public:
/**
* Writes to the stream from the supplied buffer.
*
* @param aBuf Buffer to write data from.
* @param aLen Buffer length.
*
* @return Number of bytes written.
*/
virtual int write (const char *aBuf, int aLen) = 0;
/**
* Truncates the stream from the current position and upto the end.
* The new file size will become exactly #pos() bytes.
*
* Throws ENotImplemented if this operation is not implemented for the
* given stream.
*/
virtual void truncate() = 0;
};
//////////////////////////////////////////////////////////////////////////////
/**
* The File class is a stream implementation that reads from and writes to
* regular files.
*
* The File class uses IPRT File API for file operations. Note that IPRT File
* API is not thread-safe. This means that if you pass the same RTFILE handle to
* different File instances that may be simultaneously used on different
* threads, you should care about serialization; otherwise you will get garbage
* when reading from or writing to such File instances.
*/
class VBOXXML_CLASS File : public Input, public Output
{
public:
/**
* Possible file access modes.
*/
enum Mode { Mode_Read, Mode_Write, Mode_ReadWrite };
/**
* Opens a file with the given name in the given mode. If @a aMode is Read
* or ReadWrite, the file must exist. If @a aMode is Write, the file must
* not exist. Otherwise, an EIPRTFailure excetion will be thrown.
*
* @param aMode File mode.
* @param aFileName File name.
*/
File (Mode aMode, const char *aFileName);
/**
* Uses the given file handle to perform file operations. This file
* handle must be already open in necessary mode (read, or write, or mixed).
*
* The read/write position of the given handle will be reset to the
* beginning of the file on success.
*
* Note that the given file handle will not be automatically closed upon
* this object destruction.
*
* @note It you pass the same RTFILE handle to more than one File instance,
* please make sure you have provided serialization in case if these
* instasnces are to be simultaneously used by different threads.
* Otherwise you may get garbage when reading or writing.
*
* @param aHandle Open file handle.
* @param aFileName File name (for reference).
*/
File (RTFILE aHandle, const char *aFileName = NULL);
/**
* Destrroys the File object. If the object was created from a file name
* the corresponding file will be automatically closed. If the object was
* created from a file handle, it will remain open.
*/
virtual ~File();
const char *uri() const;
uint64_t pos() const;
void setPos (uint64_t aPos);
/**
* See Input::read(). If this method is called in wrong file mode,
* LogicError will be thrown.
*/
int read (char *aBuf, int aLen);
/**
* See Output::write(). If this method is called in wrong file mode,
* LogicError will be thrown.
*/
int write (const char *aBuf, int aLen);
/**
* See Output::truncate(). If this method is called in wrong file mode,
* LogicError will be thrown.
*/
void truncate();
private:
/* Obscure class data */
struct Data;
std::auto_ptr <Data> m;
/* auto_ptr data doesn't have proper copy semantics */
DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (File)
};
/**
* The MemoryBuf class represents a stream implementation that reads from the
* memory buffer.
*/
class VBOXXML_CLASS MemoryBuf : public Input
{
public:
MemoryBuf (const char *aBuf, size_t aLen, const char *aURI = NULL);
virtual ~MemoryBuf();
const char *uri() const;
int read (char *aBuf, int aLen);
uint64_t pos() const;
void setPos (uint64_t aPos);
private:
/* Obscure class data */
struct Data;
std::auto_ptr <Data> m;
/* auto_ptr data doesn't have proper copy semantics */
DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (MemoryBuf)
};
/*
* GlobalLock
*
*
*/
typedef xmlParserInput* FNEXTERNALENTITYLOADER(const char *aURI,
const char *aID,
xmlParserCtxt *aCtxt);
typedef FNEXTERNALENTITYLOADER *PFNEXTERNALENTITYLOADER;
class VBOXXML_CLASS GlobalLock
{
public:
GlobalLock();
~GlobalLock();
void setExternalEntityLoader(PFNEXTERNALENTITYLOADER pFunc);
static xmlParserInput* callDefaultLoader(const char *aURI,
const char *aID,
xmlParserCtxt *aCtxt);
private:
/* Obscure class data */
struct Data;
std::auto_ptr<Data> m;
};
/*
* XmlParserBase
*
*/
class VBOXXML_CLASS XmlParserBase
{
protected:
XmlParserBase();
~XmlParserBase();
xmlParserCtxtPtr m_ctxt;
};
/*
* XmlFileParser
*
*/
class VBOXXML_CLASS XmlFileParser : public XmlParserBase
{
public:
XmlFileParser();
~XmlFileParser();
void read(const char *pcszFilename);
private:
/* Obscure class data */
struct Data;
std::auto_ptr<Data> m;
};
#if defined(_MSC_VER)
#pragma warning (default:4251)
#endif
#endif /* IN_RING3 */
/** @} */
} // end namespace xml
#endif /* ___VBox_vboxxml_h */