VirtualBox

Changeset 21077 in vbox for trunk/include/VBox/xml.h


Ignore:
Timestamp:
Jun 30, 2009 3:19:12 PM (15 years ago)
Author:
vboxsync
Message:

back out r49329, r49331, will start over

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/xml.h

    r21073 r21077  
     1/** @file
     2 * VirtualBox XML helper APIs.
     3 */
     4
     5/*
     6 * Copyright (C) 2007-2008 Sun Microsystems, Inc.
     7 *
     8 * This file is part of VirtualBox Open Source Edition (OSE), as
     9 * available from http://www.virtualbox.org. This file is free software;
     10 * you can redistribute it and/or modify it under the terms of the GNU
     11 * General Public License (GPL) as published by the Free Software
     12 * Foundation, in version 2 as it comes in the "COPYING" file of the
     13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
     14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
     15 *
     16 * The contents of this file may alternatively be used under the terms
     17 * of the Common Development and Distribution License Version 1.0
     18 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
     19 * VirtualBox OSE distribution, in which case the provisions of the
     20 * CDDL are applicable instead of those of the GPL.
     21 *
     22 * You may elect to license modified versions of this file under the
     23 * terms and conditions of either the GPL or the CDDL or both.
     24 *
     25 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
     26 * Clara, CA 95054 USA or visit http://www.sun.com if you need
     27 * additional information or have any questions.
     28 */
     29
     30#ifndef ___VBox_vboxxml_h
     31#define ___VBox_vboxxml_h
     32
     33#ifndef IN_RING3
     34# error "There are no XML APIs available in Ring-0 Context!"
     35#else /* IN_RING3 */
     36
     37/** @def IN_VBOXXML_R3
     38 * Used to indicate whether we're inside the same link module as the
     39 * XML Settings File Manipulation API.
     40 *
     41 * @todo should go to a separate common include together with VBOXXML2_CLASS
     42 * once there becomes more than one header in the VBoxXML2 library.
     43 */
     44#ifdef DOXYGEN_RUNNING
     45# define IN_VBOXXML_R3
     46#endif
     47
     48/** @def VBOXXML_CLASS
     49 * Class export/import wrapper. */
     50#ifdef IN_VBOXXML_R3
     51# define VBOXXML_CLASS DECLEXPORT_CLASS
     52#else
     53# define VBOXXML_CLASS DECLIMPORT_CLASS
     54#endif
     55
     56/*
     57 * Shut up MSVC complaining that auto_ptr[_ref] template instantiations (as a
     58 * result of private data member declarations of some classes below) need to
     59 * be exported too to in order to be accessible by clients.
     60 *
     61 * The alternative is to instantiate a template before the data member
     62 * declaration with the VBOXXML_CLASS prefix, but the standard disables
     63 * explicit instantiations in a foreign namespace. In other words, a declaration
     64 * like:
     65 *
     66 *   template class VBOXXML_CLASS std::auto_ptr <Data>;
     67 *
     68 * right before the member declaration makes MSVC happy too, but this is not a
     69 * valid C++ construct (and G++ spits it out). So, for now we just disable the
     70 * warning and will come back to this problem one day later.
     71 *
     72 * We also disable another warning (4275) saying that a DLL-exported class
     73 * inherits form a non-DLL-exported one (e.g. settings::ENoMemory ->
     74 * std::bad_alloc). I can't get how it can harm yet.
     75 */
     76#if defined(_MSC_VER)
     77#pragma warning (disable:4251)
     78#pragma warning (disable:4275)
     79#endif
     80
     81/* Forwards */
     82typedef struct _xmlParserInput xmlParserInput;
     83typedef xmlParserInput *xmlParserInputPtr;
     84typedef struct _xmlParserCtxt xmlParserCtxt;
     85typedef xmlParserCtxt *xmlParserCtxtPtr;
     86typedef struct _xmlError xmlError;
     87typedef xmlError *xmlErrorPtr;
     88
     89namespace xml
     90{
     91
     92// Little string class for XML only
     93//////////////////////////////////////////////////////////////////////////////
     94
     95class ministring
     96{
     97public:
     98    ministring()
     99        : m_psz(NULL)
     100    {
     101    }
     102
     103    ministring(const ministring &s)
     104        : m_psz(NULL)
     105    {
     106        copyFrom(s.c_str());
     107    }
     108
     109    ministring(const char *pcsz)
     110        : m_psz(NULL)
     111    {
     112        copyFrom(pcsz);
     113    }
     114
     115    ~ministring()
     116    {
     117        cleanup();
     118    }
     119
     120    void operator=(const char *pcsz)
     121    {
     122        cleanup();
     123        copyFrom(pcsz);
     124    }
     125
     126    void operator=(const ministring &s)
     127    {
     128        cleanup();
     129        copyFrom(s.c_str());
     130    }
     131
     132    const char* c_str() const
     133    {
     134        return m_psz;
     135    }
     136
     137private:
     138    void cleanup()
     139    {
     140        if (m_psz)
     141        {
     142            RTStrFree(m_psz);
     143            m_psz = NULL;
     144        }
     145    }
     146
     147    void copyFrom(const char *pcsz)
     148    {
     149        if (pcsz)
     150            m_psz = RTStrDup(pcsz);
     151    }
     152
     153
     154    char *m_psz;
     155};
     156
     157// Exceptions
     158//////////////////////////////////////////////////////////////////////////////
     159
     160/**
     161 * Base exception class.
     162 */
     163class VBOXXML_CLASS Error : public std::exception
     164{
     165public:
     166
     167    Error(const char *pcszMessage)
     168        : m_pcsz(NULL)
     169    {
     170        copyFrom(pcszMessage);
     171    }
     172
     173    Error(const Error &s)
     174        : std::exception(s)
     175    {
     176        copyFrom(s.what());
     177    }
     178
     179    virtual ~Error() throw()
     180    {
     181        cleanup();
     182    }
     183
     184    void operator=(const Error &s)
     185    {
     186        cleanup();
     187        copyFrom(s.what());
     188    }
     189
     190    void setWhat(const char *pcszMessage)
     191    {
     192        cleanup();
     193        copyFrom(pcszMessage);
     194    }
     195
     196    virtual const char* what() const throw()
     197    {
     198        return m_pcsz;
     199    }
     200
     201private:
     202    Error() {};     // hide the default constructor to make sure the extended one above is always used
     203
     204    void cleanup()
     205    {
     206        if (m_pcsz)
     207        {
     208            RTStrFree(m_pcsz);
     209            m_pcsz = NULL;
     210        }
     211    }
     212
     213    void copyFrom(const char *pcszMessage)
     214    {
     215        if (pcszMessage)
     216            m_pcsz = RTStrDup(pcszMessage);
     217    }
     218
     219    char *m_pcsz;
     220};
     221
     222class VBOXXML_CLASS LogicError : public Error
     223{
     224public:
     225
     226    LogicError(const char *aMsg = NULL)
     227        : xml::Error(aMsg)
     228    {}
     229
     230    LogicError(RT_SRC_POS_DECL);
     231};
     232
     233class VBOXXML_CLASS RuntimeError : public Error
     234{
     235public:
     236
     237    RuntimeError(const char *aMsg = NULL)
     238        : xml::Error(aMsg)
     239    {}
     240};
     241
     242class VBOXXML_CLASS XmlError : public RuntimeError
     243{
     244public:
     245    XmlError(xmlErrorPtr aErr);
     246
     247    static char *Format(xmlErrorPtr aErr);
     248};
     249
     250// Logical errors
     251//////////////////////////////////////////////////////////////////////////////
     252
     253class VBOXXML_CLASS ENotImplemented : public LogicError
     254{
     255public:
     256    ENotImplemented(const char *aMsg = NULL) : LogicError(aMsg) {}
     257    ENotImplemented(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
     258};
     259
     260class VBOXXML_CLASS EInvalidArg : public LogicError
     261{
     262public:
     263    EInvalidArg(const char *aMsg = NULL) : LogicError(aMsg) {}
     264    EInvalidArg(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
     265};
     266
     267class VBOXXML_CLASS EDocumentNotEmpty : public LogicError
     268{
     269public:
     270    EDocumentNotEmpty(const char *aMsg = NULL) : LogicError(aMsg) {}
     271    EDocumentNotEmpty(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
     272};
     273
     274class VBOXXML_CLASS ENodeIsNotElement : public LogicError
     275{
     276public:
     277    ENodeIsNotElement(const char *aMsg = NULL) : LogicError(aMsg) {}
     278    ENodeIsNotElement(RT_SRC_POS_DECL) : LogicError(RT_SRC_POS_ARGS) {}
     279};
     280
     281// Runtime errors
     282//////////////////////////////////////////////////////////////////////////////
     283
     284class VBOXXML_CLASS ENoMemory : public RuntimeError, public std::bad_alloc
     285{
     286public:
     287    ENoMemory(const char *aMsg = NULL) : RuntimeError (aMsg) {}
     288    virtual ~ENoMemory() throw() {}
     289};
     290
     291class VBOXXML_CLASS EIPRTFailure : public RuntimeError
     292{
     293public:
     294
     295    EIPRTFailure (int aRC);
     296
     297    int rc() const { return mRC; }
     298
     299private:
     300    int mRC;
     301};
     302
     303
     304/**
     305 * The Stream class is a base class for I/O streams.
     306 */
     307class VBOXXML_CLASS Stream
     308{
     309public:
     310
     311    virtual ~Stream() {}
     312
     313    virtual const char *uri() const = 0;
     314
     315    /**
     316     * Returns the current read/write position in the stream. The returned
     317     * position is a zero-based byte offset from the beginning of the file.
     318     *
     319     * Throws ENotImplemented if this operation is not implemented for the
     320     * given stream.
     321     */
     322    virtual uint64_t pos() const = 0;
     323
     324    /**
     325     * Sets the current read/write position in the stream.
     326     *
     327     * @param aPos Zero-based byte offset from the beginning of the stream.
     328     *
     329     * Throws ENotImplemented if this operation is not implemented for the
     330     * given stream.
     331     */
     332    virtual void setPos (uint64_t aPos) = 0;
     333};
     334
     335/**
     336 * The Input class represents an input stream.
     337 *
     338 * This input stream is used to read the settings tree from.
     339 * This is an abstract class that must be subclassed in order to fill it with
     340 * useful functionality.
     341 */
     342class VBOXXML_CLASS Input : virtual public Stream
     343{
     344public:
     345
     346    /**
     347     * Reads from the stream to the supplied buffer.
     348     *
     349     * @param aBuf Buffer to store read data to.
     350     * @param aLen Buffer length.
     351     *
     352     * @return Number of bytes read.
     353     */
     354    virtual int read (char *aBuf, int aLen) = 0;
     355};
     356
     357/**
     358 *
     359 */
     360class VBOXXML_CLASS Output : virtual public Stream
     361{
     362public:
     363
     364    /**
     365     * Writes to the stream from the supplied buffer.
     366     *
     367     * @param aBuf Buffer to write data from.
     368     * @param aLen Buffer length.
     369     *
     370     * @return Number of bytes written.
     371     */
     372    virtual int write (const char *aBuf, int aLen) = 0;
     373
     374    /**
     375     * Truncates the stream from the current position and upto the end.
     376     * The new file size will become exactly #pos() bytes.
     377     *
     378     * Throws ENotImplemented if this operation is not implemented for the
     379     * given stream.
     380     */
     381    virtual void truncate() = 0;
     382};
     383
     384
     385//////////////////////////////////////////////////////////////////////////////
     386
     387/**
     388 * The File class is a stream implementation that reads from and writes to
     389 * regular files.
     390 *
     391 * The File class uses IPRT File API for file operations. Note that IPRT File
     392 * API is not thread-safe. This means that if you pass the same RTFILE handle to
     393 * different File instances that may be simultaneously used on different
     394 * threads, you should care about serialization; otherwise you will get garbage
     395 * when reading from or writing to such File instances.
     396 */
     397class VBOXXML_CLASS File : public Input, public Output
     398{
     399public:
     400
     401    /**
     402     * Possible file access modes.
     403     */
     404    enum Mode { Mode_Read, Mode_WriteCreate, Mode_Overwrite, Mode_ReadWrite };
     405
     406    /**
     407     * Opens a file with the given name in the given mode. If @a aMode is Read
     408     * or ReadWrite, the file must exist. If @a aMode is Write, the file must
     409     * not exist. Otherwise, an EIPRTFailure excetion will be thrown.
     410     *
     411     * @param aMode     File mode.
     412     * @param aFileName File name.
     413     */
     414    File (Mode aMode, const char *aFileName);
     415
     416    /**
     417     * Uses the given file handle to perform file operations. This file
     418     * handle must be already open in necessary mode (read, or write, or mixed).
     419     *
     420     * The read/write position of the given handle will be reset to the
     421     * beginning of the file on success.
     422     *
     423     * Note that the given file handle will not be automatically closed upon
     424     * this object destruction.
     425     *
     426     * @note It you pass the same RTFILE handle to more than one File instance,
     427     *       please make sure you have provided serialization in case if these
     428     *       instasnces are to be simultaneously used by different threads.
     429     *       Otherwise you may get garbage when reading or writing.
     430     *
     431     * @param aHandle   Open file handle.
     432     * @param aFileName File name (for reference).
     433     */
     434    File (RTFILE aHandle, const char *aFileName = NULL);
     435
     436    /**
     437     * Destroys the File object. If the object was created from a file name
     438     * the corresponding file will be automatically closed. If the object was
     439     * created from a file handle, it will remain open.
     440     */
     441    virtual ~File();
     442
     443    const char *uri() const;
     444
     445    uint64_t pos() const;
     446    void setPos (uint64_t aPos);
     447
     448    /**
     449     * See Input::read(). If this method is called in wrong file mode,
     450     * LogicError will be thrown.
     451     */
     452    int read (char *aBuf, int aLen);
     453
     454    /**
     455     * See Output::write(). If this method is called in wrong file mode,
     456     * LogicError will be thrown.
     457     */
     458    int write (const char *aBuf, int aLen);
     459
     460    /**
     461     * See Output::truncate(). If this method is called in wrong file mode,
     462     * LogicError will be thrown.
     463     */
     464    void truncate();
     465
     466private:
     467
     468    /* Obscure class data */
     469    struct Data;
     470    std::auto_ptr <Data> m;
     471
     472    /* auto_ptr data doesn't have proper copy semantics */
     473    DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (File)
     474};
     475
     476/**
     477 * The MemoryBuf class represents a stream implementation that reads from the
     478 * memory buffer.
     479 */
     480class VBOXXML_CLASS MemoryBuf : public Input
     481{
     482public:
     483
     484    MemoryBuf (const char *aBuf, size_t aLen, const char *aURI = NULL);
     485
     486    virtual ~MemoryBuf();
     487
     488    const char *uri() const;
     489
     490    int read (char *aBuf, int aLen);
     491    uint64_t pos() const;
     492    void setPos (uint64_t aPos);
     493
     494private:
     495    /* Obscure class data */
     496    struct Data;
     497    std::auto_ptr <Data> m;
     498
     499    /* auto_ptr data doesn't have proper copy semantics */
     500    DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (MemoryBuf)
     501};
     502
     503
     504/*
     505 * GlobalLock
     506 *
     507 *
     508 */
     509
     510typedef xmlParserInput* FNEXTERNALENTITYLOADER(const char *aURI,
     511                                               const char *aID,
     512                                               xmlParserCtxt *aCtxt);
     513typedef FNEXTERNALENTITYLOADER *PFNEXTERNALENTITYLOADER;
     514
     515class VBOXXML_CLASS GlobalLock
     516{
     517public:
     518    GlobalLock();
     519    ~GlobalLock();
     520
     521    void setExternalEntityLoader(PFNEXTERNALENTITYLOADER pFunc);
     522
     523    static xmlParserInput* callDefaultLoader(const char *aURI,
     524                                             const char *aID,
     525                                             xmlParserCtxt *aCtxt);
     526
     527private:
     528    /* Obscure class data. */
     529    struct Data;
     530    struct Data *m;
     531};
     532
     533/**
     534 * Node:
     535 *  an XML node, which represents either an element or text content
     536 *  or an attribute.
     537 *
     538 *  For elements, getName() returns the element name, and getValue()
     539 *  returns the text contents, if any.
     540 *
     541 *  For attributes, getName() returns the attribute name, and getValue()
     542 *  returns the attribute value, if any.
     543 *
     544 *  Since the default constructor is private, one can create new nodes
     545 *  only through factory methods provided by the XML classes. These are:
     546 *
     547 *  --  xml::Document::createRootElement()
     548 *  --  xml::Node::createChild()
     549 *  --  xml::Node::addContent()
     550 *  --  xml::Node::setAttribute()
     551 */
     552
     553class ElementNode;
     554typedef std::list<const ElementNode*> ElementNodesList;
     555
     556class AttributeNode;
     557
     558class ContentNode;
     559
     560class VBOXXML_CLASS Node
     561{
     562public:
     563    ~Node();
     564
     565    const char* getName() const;
     566    const char* getValue() const;
     567    bool copyValue(int32_t &i) const;
     568    bool copyValue(uint32_t &i) const;
     569    bool copyValue(int64_t &i) const;
     570    bool copyValue(uint64_t &i) const;
     571
     572    int getLineNumber() const;
     573
     574    int isElement()
     575    {
     576        return mType == IsElement;
     577    }
     578
     579protected:
     580    typedef enum {IsElement, IsAttribute, IsContent} EnumType;
     581    EnumType mType;
     582
     583    // hide the default constructor so people use only our factory methods
     584    Node(EnumType type);
     585    Node(const Node &x);      // no copying
     586
     587    void buildChildren();
     588
     589    /* Obscure class data */
     590    struct Data;
     591    Data *m;
     592};
     593
     594class VBOXXML_CLASS ElementNode : public Node
     595{
     596public:
     597    int getChildElements(ElementNodesList &children,
     598                         const char *pcszMatch = NULL) const;
     599
     600    const ElementNode* findChildElement(const char *pcszMatch) const;
     601    const ElementNode* findChildElementFromId(const char *pcszId) const;
     602
     603    const AttributeNode* findAttribute(const char *pcszMatch) const;
     604    bool getAttributeValue(const char *pcszMatch, const char *&ppcsz) const;
     605    bool getAttributeValue(const char *pcszMatch, int64_t &i) const;
     606    bool getAttributeValue(const char *pcszMatch, uint64_t &i) const;
     607
     608    ElementNode* createChild(const char *pcszElementName);
     609    ContentNode* addContent(const char *pcszContent);
     610    AttributeNode* setAttribute(const char *pcszName, const char *pcszValue);
     611
     612protected:
     613    // hide the default constructor so people use only our factory methods
     614    ElementNode();
     615    ElementNode(const ElementNode &x);      // no copying
     616
     617    friend class Node;
     618    friend class Document;
     619    friend class XmlFileParser;
     620};
     621
     622class VBOXXML_CLASS ContentNode : public Node
     623{
     624public:
     625
     626protected:
     627    // hide the default constructor so people use only our factory methods
     628    ContentNode();
     629    ContentNode(const ContentNode &x);      // no copying
     630
     631    friend class Node;
     632    friend class ElementNode;
     633};
     634
     635class VBOXXML_CLASS AttributeNode : public Node
     636{
     637public:
     638
     639protected:
     640    // hide the default constructor so people use only our factory methods
     641    AttributeNode();
     642    AttributeNode(const AttributeNode &x);      // no copying
     643
     644    friend class Node;
     645    friend class ElementNode;
     646};
     647
     648/*
     649 * NodesLoop
     650 *
     651 */
     652
     653class VBOXXML_CLASS NodesLoop
     654{
     655public:
     656    NodesLoop(const ElementNode &node, const char *pcszMatch = NULL);
     657    ~NodesLoop();
     658    const ElementNode* forAllNodes() const;
     659
     660private:
     661    /* Obscure class data */
     662    struct Data;
     663    Data *m;
     664};
     665
     666/*
     667 * Document
     668 *
     669 */
     670
     671class VBOXXML_CLASS Document
     672{
     673public:
     674    Document();
     675    ~Document();
     676
     677    Document(const Document &x);
     678    Document& operator=(const Document &x);
     679
     680    const ElementNode* getRootElement() const;
     681
     682    ElementNode* createRootElement(const char *pcszRootElementName);
     683
     684private:
     685    friend class XmlFileParser;
     686    friend class XmlFileWriter;
     687
     688    void refreshInternals();
     689
     690    /* Obscure class data */
     691    struct Data;
     692    Data *m;
     693};
     694
     695/*
     696 * XmlParserBase
     697 *
     698 */
     699
     700class VBOXXML_CLASS XmlParserBase
     701{
     702protected:
     703    XmlParserBase();
     704    ~XmlParserBase();
     705
     706    xmlParserCtxtPtr m_ctxt;
     707};
     708
     709/*
     710 * XmlFileParser
     711 *
     712 */
     713
     714class VBOXXML_CLASS XmlFileParser : public XmlParserBase
     715{
     716public:
     717    XmlFileParser();
     718    ~XmlFileParser();
     719
     720    void read(const char *pcszFilename, Document &doc);
     721
     722private:
     723    /* Obscure class data */
     724    struct Data;
     725    struct Data *m;
     726
     727    static int ReadCallback(void *aCtxt, char *aBuf, int aLen);
     728    static int CloseCallback (void *aCtxt);
     729};
     730
     731/*
     732 * XmlFileWriter
     733 *
     734 */
     735
     736class VBOXXML_CLASS XmlFileWriter
     737{
     738public:
     739    XmlFileWriter(Document &doc);
     740    ~XmlFileWriter();
     741
     742    void write(const char *pcszFilename);
     743
     744    static int WriteCallback(void *aCtxt, const char *aBuf, int aLen);
     745    static int CloseCallback (void *aCtxt);
     746
     747private:
     748    /* Obscure class data */
     749    struct Data;
     750    Data *m;
     751};
     752
     753#if defined(_MSC_VER)
     754#pragma warning (default:4251)
     755#endif
     756
     757#endif /* IN_RING3 */
     758
     759/** @} */
     760
     761} // end namespace xml
     762
     763#endif /* ___VBox_vboxxml_h */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette