VirtualBox

Changeset 48834 in vbox for trunk/include/iprt


Ignore:
Timestamp:
Oct 3, 2013 1:28:57 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
89503
Message:

iprt/xml: Added more convenience methods and did more cleanup work, the latter reducing aimed at removing boost and reducing the number of allocations and their sizes. Changed the tree building code to be non-recursive. Attributes and child lists moved from Node to ElementNode, as only elements have them (in or simplified model at least). Dropped the attribute map in favor of a doubly linked list, doubt there will be any performance issue here even with 15-20 attributes (besides element lookup is list based). Also dropped the 'Node::m' member that pointed to a couple of obscure internal members (attribute and child collections), no longer needed.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/cpp/xml.h

    r48797 r48834  
    3131#endif
    3232
    33 /*#define USE_STD_LIST_FOR_CHILDREN*/
    34 
    3533#include <iprt/list.h>
    3634#include <iprt/cpp/exception.h>
     35#include <iprt/cpp/utils.h>
    3736
    3837#include <list>
     
    395394{
    396395public:
    397     ~Node();
     396    virtual ~Node();
    398397
    399398    const char *getName() const;
     
    437436
    438437    int getLineNumber() const;
    439 
    440438    /** @} */
    441439
    442 #ifndef USE_STD_LIST_FOR_CHILDREN
    443440    /** @name General tree enumeration.
    444441     *
     
    447444     * can be of both ContentNode and ElementNode types.
    448445     *
     446     * @remarks Attribute node are in the attributes list, while both content and
     447     *          element nodes are in the list of children. See ElementNode.
     448     *
    449449     * @remarks Careful mixing tree walking with node removal!
    450450     * @{
     
    457457    }
    458458
    459     /** Get the first child node.
    460      * @returns Pointer to the first child node, NULL if no children. */
    461     const Node *getFirstChild() const
    462     {
    463         return RTListGetFirstCpp(&m_children, const Node, m_childEntry);
    464     }
    465 
    466     /** Get the last child node.
    467      * @returns Pointer to the last child node, NULL if no children. */
    468     const Node *getLastChild() const
    469     {
    470         return RTListGetLastCpp(&m_children, const Node, m_childEntry);
    471     }
    472 
    473459    /** Get the previous sibling.
    474      * @returns Pointer to the previous sibling node, NULL if first child. */
     460     * @returns Pointer to the previous sibling node, NULL if first child.
     461     */
    475462    const Node *getPrevSibiling() const
    476463    {
    477         if (!m_pParent)
     464        if (!m_pParentListAnchor)
    478465            return NULL;
    479         return RTListGetPrevCpp(&m_pParent->m_children, this, const Node, m_childEntry);
     466        return RTListGetPrevCpp(m_pParentListAnchor, this, const Node, m_listEntry);
    480467    }
    481468
     
    484471    const Node *getNextSibiling() const
    485472    {
    486         if (!m_pParent)
     473        if (!m_pParentListAnchor)
    487474            return NULL;
    488         return RTListGetNextCpp(&m_pParent->m_children, this, const Node, m_childEntry);
     475        return RTListGetNextCpp(m_pParentListAnchor, this, const Node, m_listEntry);
    489476    }
    490477    /** @} */
    491 #endif
    492478
    493479protected:
     
    495481    typedef enum { IsElement, IsAttribute, IsContent } EnumType;
    496482
    497     EnumType    m_Type;                 /**< The type of node this is an instance of. */
    498     Node       *m_pParent;              /**< The parent node, NULL if root. */
    499     xmlNode    *m_plibNode;            ///< != NULL if this is an element or content node
    500     xmlAttr    *m_plibAttr;            ///< != NULL if this is an attribute node
     483    /** The type of node this is an instance of. */
     484    EnumType    m_Type;
     485    /** The parent node (always an element), NULL if root. */
     486    Node       *m_pParent;
     487
     488    xmlNode    *m_pLibNode;            ///< != NULL if this is an element or content node
     489    xmlAttr    *m_pLibAttr;            ///< != NULL if this is an attribute node
    501490    const char *m_pcszNamespacePrefix; ///< not always set
    502491    const char *m_pcszNamespaceHref;   ///< full http:// spec
    503     const char *m_pcszName;            ///< element or attribute name, points either into plibNode or plibAttr;
     492    const char *m_pcszName;            ///< element or attribute name, points either into pLibNode or pLibAttr;
    504493                                       ///< NULL if this is a content node
    505494
    506 #ifndef USE_STD_LIST_FOR_CHILDREN
    507495    /** Child list entry of this node. (List head m_pParent->m_children.) */
    508     RTLISTNODE      m_childEntry;
    509     /** Child elements, if this is an element; can be empty. */
    510     RTLISTANCHOR    m_children;
    511 #endif
     496    RTLISTNODE      m_listEntry;
     497    /** Pointer to the parent list anchor.
     498     * This allows us to use m_listEntry both for children and attributes. */
     499    PRTLISTANCHOR   m_pParentListAnchor;
    512500
    513501    // hide the default constructor so people use only our factory methods
    514502    Node(EnumType type,
    515503         Node *pParent,
    516          xmlNode *plibNode,
    517          xmlAttr *plibAttr);
     504         PRTLISTANCHOR pListAnchor,
     505         xmlNode *pLibNode,
     506         xmlAttr *pLibAttr);
    518507    Node(const Node &x);      // no copying
    519 
    520     void buildChildren(const ElementNode &elmRoot);
    521 
    522     /* Obscure class data */
    523     struct Data;
    524     Data *m;
    525508
    526509    friend class AttributeNode;
     
    545528protected:
    546529    // hide the default constructor so people use only our factory methods
    547     AttributeNode(const ElementNode &elmRoot,
     530    AttributeNode(const ElementNode *pElmRoot,
    548531                  Node *pParent,
    549                   xmlAttr *plibAttr,
    550                   const char **ppcszKey);
     532                  PRTLISTANCHOR pListAnchor,
     533                  xmlAttr *pLibAttr);
    551534    AttributeNode(const AttributeNode &x);      // no copying
    552535
     536    /** For storing attribute names with namespace prefix.
     537     * Only used if with non-default namespace specified. */
    553538    RTCString    m_strKey;
    554539
     
    615600    }
    616601
    617 
    618     /** @name Element enumeration.
     602    /** Combines findChildElementP and findAttributeValue.
     603     *
     604     * @returns Pointer to attribute string value, NULL if either the element or
     605     *          the attribute was not found.
     606     * @param   pcszPath            The attribute name.  Slashes can be used to make a
     607     *                              simple path to any decendant.
     608     * @param   pcszAttribute       The attribute name.
     609     * @param   pcszPathNamespace   The namespace to match @pcszPath with, NULL
     610     *                              (default) match any namespace.  When using a
     611     *                              path, this matches all elements along the way.
     612     * @see     findChildElementP and findAttributeValue
     613     */
     614    const char *findChildElementAttributeValueP(const char *pcszPath, const char *pcszAttribute,
     615                                                const char *pcszPathNamespace = NULL) const
     616    {
     617        const ElementNode *pElem = findChildElementP(pcszPath, pcszPathNamespace);
     618        if (pElem)
     619            return pElem->findAttributeValue(pcszAttribute);
     620        return NULL;
     621    }
     622
     623
     624    /** @name Tree enumeration.
    619625     * @{ */
     626
     627    /** Get the next tree element in a full tree enumeration.
     628     *
     629     * By starting with the root node, this can be used to enumerate the entire tree
     630     * (or sub-tree if @a pElmRoot is used).
     631     *
     632     * @returns Pointer to the next element in the tree, NULL if we're done.
     633     * @param   pElmRoot            The root of the tree we're enumerating.  NULL if
     634     *                              it's the entire tree.
     635     */
     636    ElementNode const *getNextTreeElement(ElementNode const *pElmRoot = NULL) const;
     637    RT_CPP_GETTER_UNCONST_RET(ElementNode *, ElementNode, getNextTreeElement, (const ElementNode *pElmRoot = NULL), (pElmRoot))
     638
     639    /** Get the first child node.
     640     * @returns Pointer to the first child node, NULL if no children. */
     641    const Node *getFirstChild() const
     642    {
     643        return RTListGetFirstCpp(&m_children, const Node, m_listEntry);
     644    }
     645    RT_CPP_GETTER_UNCONST_RET(Node *, ElementNode, getFirstChild,(),())
     646
     647    /** Get the last child node.
     648     * @returns Pointer to the last child node, NULL if no children. */
     649    const Node *getLastChild() const
     650    {
     651        return RTListGetLastCpp(&m_children, const Node, m_listEntry);
     652    }
     653
     654    /** Get the first child node.
     655     * @returns Pointer to the first child node, NULL if no children. */
     656    const ElementNode *getFirstChildElement() const;
     657
     658    /** Get the last child node.
     659     * @returns Pointer to the last child node, NULL if no children. */
     660    const ElementNode *getLastChildElement() const;
     661
    620662    /** Get the previous sibling element.
    621663     * @returns Pointer to the previous sibling element, NULL if first child
     
    667709    }
    668710
    669     bool getAttributeValue(const char *pcszMatch, const char *&pcsz) const;
     711    bool getAttributeValue(const char *pcszMatch, const char *&pcsz) const  { return getAttributeValue(pcszMatch, &pcsz); }
    670712    bool getAttributeValue(const char *pcszMatch, RTCString &str) const;
    671713    bool getAttributeValuePath(const char *pcszMatch, RTCString &str) const;
    672714    bool getAttributeValue(const char *pcszMatch, int32_t &i) const;
    673715    bool getAttributeValue(const char *pcszMatch, uint32_t &i) const;
    674     bool getAttributeValue(const char *pcszMatch, int64_t &i) const;
     716    bool getAttributeValue(const char *pcszMatch, int64_t &i) const         { return getAttributeValue(pcszMatch, &i); }
    675717    bool getAttributeValue(const char *pcszMatch, uint64_t &i) const;
    676718    bool getAttributeValue(const char *pcszMatch, bool &f) const;
     
    678720    /** @name Variants that for clarity does not use references for output params.
    679721     * @{ */
    680     bool getAttributeValue(const char *pcszMatch, const char **ppcsz) const { return getAttributeValue(pcszMatch, *ppcsz); }
     722    bool getAttributeValue(const char *pcszMatch, const char **ppcsz) const;
    681723    bool getAttributeValue(const char *pcszMatch, RTCString *pStr) const    { return getAttributeValue(pcszMatch, *pStr); }
    682724    bool getAttributeValuePath(const char *pcszMatch, RTCString *pStr) const { return getAttributeValuePath(pcszMatch, *pStr); }
    683725    bool getAttributeValue(const char *pcszMatch, int32_t *pi) const        { return getAttributeValue(pcszMatch, *pi); }
    684726    bool getAttributeValue(const char *pcszMatch, uint32_t *pu) const       { return getAttributeValue(pcszMatch, *pu); }
    685     bool getAttributeValue(const char *pcszMatch, int64_t *pi) const        { return getAttributeValue(pcszMatch, *pi); }
     727    bool getAttributeValue(const char *pcszMatch, int64_t *piValue) const;
    686728    bool getAttributeValue(const char *pcszMatch, uint64_t *pu) const       { return getAttributeValue(pcszMatch, *pu); }
    687729    bool getAttributeValue(const char *pcszMatch, bool *pf) const           { return getAttributeValue(pcszMatch, *pf); }
    688730    /** @} */
    689731
     732    /** @name Convenience methods for convering the element value.
     733     * @{ */
     734    bool getElementValue(int32_t  *piValue) const;
     735    bool getElementValue(uint32_t *puValue) const;
     736    bool getElementValue(int64_t  *piValue) const;
     737    bool getElementValue(uint64_t *puValue) const;
     738    bool getElementValue(bool     *pfValue) const;
     739    /** @} */
     740
     741    /** @name Convenience findChildElementAttributeValueP and getElementValue.
     742     * @{ */
     743    bool getChildElementValueP(const char *pcszPath, int32_t  *piValue, const char *pcszNamespace = NULL) const
     744    {
     745        const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
     746        return pElem && pElem->getElementValue(piValue);
     747    }
     748    bool getChildElementValueP(const char *pcszPath, uint32_t *puValue, const char *pcszNamespace = NULL) const
     749    {
     750        const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
     751        return pElem && pElem->getElementValue(puValue);
     752    }
     753    bool getChildElementValueP(const char *pcszPath, int64_t  *piValue, const char *pcszNamespace = NULL) const
     754    {
     755        const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
     756        return pElem && pElem->getElementValue(piValue);
     757    }
     758    bool getChildElementValueP(const char *pcszPath, uint64_t *puValue, const char *pcszNamespace = NULL) const
     759    {
     760        const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
     761        return pElem && pElem->getElementValue(puValue);
     762    }
     763    bool getChildElementValueP(const char *pcszPath, bool     *pfValue, const char *pcszNamespace = NULL) const
     764    {
     765        const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
     766        return pElem && pElem->getElementValue(pfValue);
     767    }
     768
     769    /** @} */
     770
     771    /** @name Convenience findChildElementAttributeValueP and getElementValue with a
     772     *        default value being return if the child element isn't present.
     773     *
     774     * @remarks These will return false on conversion errors.
     775     * @{ */
     776    bool getChildElementValueDefP(const char *pcszPath, int32_t  iDefault, int32_t  *piValue, const char *pcszNamespace = NULL) const
     777    {
     778        const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
     779        if (pElem)
     780            return pElem->getElementValue(piValue);
     781        *piValue = iDefault;
     782        return true;
     783    }
     784    bool getChildElementValueDefP(const char *pcszPath, uint32_t uDefault, uint32_t *puValue, const char *pcszNamespace = NULL) const
     785    {
     786        const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
     787        if (pElem)
     788            return pElem->getElementValue(puValue);
     789        *puValue = uDefault;
     790        return true;
     791    }
     792    bool getChildElementValueDefP(const char *pcszPath, int64_t  iDefault, int64_t  *piValue, const char *pcszNamespace = NULL) const
     793    {
     794        const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
     795        if (pElem)
     796            return pElem->getElementValue(piValue);
     797        *piValue = iDefault;
     798        return true;
     799    }
     800    bool getChildElementValueDefP(const char *pcszPath, uint64_t uDefault, uint64_t *puValue, const char *pcszNamespace = NULL) const
     801    {
     802        const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
     803        if (pElem)
     804            return pElem->getElementValue(puValue);
     805        *puValue = uDefault;
     806        return true;
     807    }
     808    bool getChildElementValueDefP(const char *pcszPath, bool     fDefault, bool     *pfValue, const char *pcszNamespace = NULL) const
     809    {
     810        const ElementNode *pElem = findChildElementP(pcszPath, pcszNamespace);
     811        if (pElem)
     812            return pElem->getElementValue(pfValue);
     813        *pfValue = fDefault;
     814        return true;
     815    }
     816    /** @} */
    690817
    691818    ElementNode *createChild(const char *pcszElementName);
     
    712839protected:
    713840    // hide the default constructor so people use only our factory methods
    714     ElementNode(const ElementNode *pelmRoot, Node *pParent, xmlNode *plibNode);
     841    ElementNode(const ElementNode *pElmRoot, Node *pParent, PRTLISTANCHOR pListAnchor, xmlNode *pLibNode);
    715842    ElementNode(const ElementNode &x);      // no copying
    716 
    717     const ElementNode *m_pelmRoot;
     843    virtual ElementNode::~ElementNode();
     844
     845    /** We keep a pointer to the root element for attribute namespace handling. */
     846    const ElementNode  *m_pElmRoot;
     847
     848    /** List of child elements and content nodes. */
     849    RTLISTANCHOR        m_children;
     850    /** List of attributes nodes. */
     851    RTLISTANCHOR        m_attributes;
     852
     853    static void buildChildren(ElementNode *pElmRoot);
    718854
    719855    friend class Node;
     
    736872protected:
    737873    // hide the default constructor so people use only our factory methods
    738     ContentNode(Node *pParent, xmlNode *plibNode);
     874    ContentNode(Node *pParent, PRTLISTANCHOR pListAnchor, xmlNode *pLibNode);
    739875    ContentNode(const ContentNode &x);      // no copying
    740876
     
    772908    XmlFileParser parser;
    773909    parser.read("file.xml", doc);
    774     Element *pelmRoot = doc.getRootElement();
     910    Element *pElmRoot = doc.getRootElement();
    775911   @endcode
    776912 *
     
    780916 * @code
    781917    Document doc;
    782     Element *pelmRoot = doc.createRootElement();
     918    Element *pElmRoot = doc.createRootElement();
    783919    // add children
    784920    xml::XmlFileWriter writer(doc);
Note: See TracChangeset for help on using the changeset viewer.

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