/** @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 #include /* these conflict with numeric_digits<>::min and max */ #undef min #undef max #include #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 ; * * 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: // Error() {}; // hide the default constructor to make sure the extended one above is always used /** 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 m; }; class VBOXXML_CLASS LogicError : public Error { public: LogicError (const char *aMsg = NULL) : xml::Error(aMsg) {} LogicError (RT_SRC_POS_DECL); }; class VBOXXML_CLASS RuntimeError : public Error { public: RuntimeError (const char *aMsg = NULL) : Error (aMsg) {} }; class VBOXXML_CLASS XmlError : public RuntimeError { public: XmlError(xmlErrorPtr aErr); static char *Format(xmlErrorPtr aErr); }; // 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 (int 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 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 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 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 m; static int ReadCallback(void *aCtxt, char *aBuf, int aLen); static int CloseCallback (void *aCtxt); }; #if defined(_MSC_VER) #pragma warning (default:4251) #endif #endif /* IN_RING3 */ /** @} */ } // end namespace xml #endif /* ___VBox_vboxxml_h */