VirtualBox

Changeset 48834 in vbox


Ignore:
Timestamp:
Oct 3, 2013 1:28:57 PM (11 years ago)
Author:
vboxsync
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.

Location:
trunk
Files:
2 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);
  • trunk/src/VBox/Runtime/r3/xml.cpp

    r48797 r48834  
    4747
    4848#include <map>
    49 #include <boost/shared_ptr.hpp> /* This is the ONLY use of boost. */
    5049
    5150
     
    156155    RTStrAPrintfV(&pszContext2, pcszContext, args);
    157156    char *newMsg;
    158     RTStrAPrintf(&newMsg, "%s: %d (%s)", pszContext2, aRC, RTErrGetShort(aRC));
     157    RTStrAPrintf(&newMsg, "%s: %d(%s)", pszContext2, aRC, RTErrGetShort(aRC));
    159158    setWhat(newMsg);
    160159    RTStrFree(newMsg);
     
    241240}
    242241
    243 const char* File::uri() const
     242const char *File::uri() const
    244243{
    245244    return m->strFileName.c_str();
     
    291290{
    292291    size_t len = aLen;
    293     int vrc = RTFileWrite (m->handle, aBuf, len, &len);
    294     if (RT_SUCCESS (vrc))
     292    int vrc = RTFileWrite(m->handle, aBuf, len, &len);
     293    if (RT_SUCCESS(vrc))
    295294        return (int)len;
    296295
    297296    throw EIPRTFailure(vrc, "Runtime error writing to file '%s'", m->strFileName.c_str());
    298 
    299     return -1 /* failure */;
    300297}
    301298
    302299void File::truncate()
    303300{
    304     int vrc = RTFileSetSize (m->handle, pos());
    305     if (RT_SUCCESS (vrc))
     301    int vrc = RTFileSetSize(m->handle, pos());
     302    if (RT_SUCCESS(vrc))
    306303        return;
    307304
     
    318315{
    319316    Data()
    320         : buf (NULL), len (0), uri (NULL), pos (0) {}
     317        : buf(NULL), len(0), uri(NULL), pos(0) {}
    321318
    322319    const char *buf;
     
    327324};
    328325
    329 MemoryBuf::MemoryBuf (const char *aBuf, size_t aLen, const char *aURI /* = NULL */)
    330     : m (new Data())
     326MemoryBuf::MemoryBuf(const char *aBuf, size_t aLen, const char *aURI /* = NULL */)
     327    : m(new Data())
    331328{
    332329    if (aBuf == NULL)
    333         throw EInvalidArg (RT_SRC_POS);
     330        throw EInvalidArg(RT_SRC_POS);
    334331
    335332    m->buf = aBuf;
    336333    m->len = aLen;
    337     m->uri = RTStrDup (aURI);
     334    m->uri = RTStrDup(aURI);
    338335}
    339336
    340337MemoryBuf::~MemoryBuf()
    341338{
    342     RTStrFree (m->uri);
     339    RTStrFree(m->uri);
    343340}
    344341
     
    353350}
    354351
    355 void MemoryBuf::setPos (uint64_t aPos)
    356 {
    357     size_t off = (size_t) aPos;
     352void MemoryBuf::setPos(uint64_t aPos)
     353{
     354    size_t off = (size_t)aPos;
    358355    if ((uint64_t) off != aPos)
    359356        throw EInvalidArg();
     
    365362}
    366363
    367 int MemoryBuf::read (char *aBuf, int aLen)
     364int MemoryBuf::read(char *aBuf, int aLen)
    368365{
    369366    if (m->pos >= m->len)
     
    371368
    372369    size_t len = m->pos + aLen < m->len ? aLen : m->len - m->pos;
    373     memcpy (aBuf, m->buf + m->pos, len);
     370    memcpy(aBuf, m->buf + m->pos, len);
    374371    m->pos += len;
    375372
     
    422419}
    423420
     421
     422
    424423////////////////////////////////////////////////////////////////////////////////
    425424//
     
    427426//
    428427////////////////////////////////////////////////////////////////////////////////
    429 
    430 struct Node::Data
    431 {
    432     struct compare_const_char
    433     {
    434         bool operator()(const char* s1, const char* s2) const
    435         {
    436             return strcmp(s1, s2) < 0;
    437         }
    438     };
    439 
    440     // attributes, if this is an element; can be empty
    441     typedef std::map<const char*, boost::shared_ptr<AttributeNode>, compare_const_char > AttributesMap;
    442     AttributesMap attribs;
    443 
    444 #ifdef USE_STD_LIST_FOR_CHILDREN
    445     // child elements, if this is an element; can be empty
    446     typedef std::list< boost::shared_ptr<Node> > InternalNodesList;
    447     InternalNodesList children;
    448 #endif
    449 };
    450428
    451429Node::Node(EnumType type,
    452430           Node *pParent,
    453            xmlNode *plibNode,
    454            xmlAttr *plibAttr)
     431           PRTLISTANCHOR pListAnchor,
     432           xmlNode *pLibNode,
     433           xmlAttr *pLibAttr)
    455434    : m_Type(type)
    456435    , m_pParent(pParent)
    457     , m_plibNode(plibNode)
    458     , m_plibAttr(plibAttr)
     436    , m_pLibNode(pLibNode)
     437    , m_pLibAttr(pLibAttr)
    459438    , m_pcszNamespacePrefix(NULL)
    460439    , m_pcszNamespaceHref(NULL)
    461440    , m_pcszName(NULL)
    462     , m(new Data)
    463 {
    464 #ifndef USE_STD_LIST_FOR_CHILDREN
    465     RTListInit(&m_childEntry);
    466     RTListInit(&m_children);
    467 #endif
     441    , m_pParentListAnchor(pListAnchor)
     442{
     443    RTListInit(&m_listEntry);
    468444}
    469445
    470446Node::~Node()
    471447{
    472 #ifndef USE_STD_LIST_FOR_CHILDREN
    473     Node *pCur, *pNext;
    474     RTListForEachSafeCpp(&m_children, pCur, pNext, Node, m_childEntry)
    475     {
    476         delete pCur;
    477     }
    478     RTListInit(&m_children);
    479 #endif
    480     delete m;
    481 }
    482 
    483 /**
    484  * Private implementation.
    485  * @param elmRoot
    486  */
    487 void Node::buildChildren(const ElementNode &elmRoot)       // private
    488 {
    489     // go thru this element's attributes
    490     xmlAttr *plibAttr = m_plibNode->properties;
    491     while (plibAttr)
    492     {
    493         const char *pcszKey;
    494         boost::shared_ptr<AttributeNode> pNew(new AttributeNode(elmRoot, this, plibAttr, &pcszKey));
    495         // store
    496         m->attribs[pcszKey] = pNew;
    497 
    498         plibAttr = plibAttr->next;
    499     }
    500 
    501     // go thru this element's child elements
    502     for (xmlNodePtr plibNode = m_plibNode->children; plibNode; plibNode = plibNode->next)
    503     {
    504 #ifndef USE_STD_LIST_FOR_CHILDREN
    505         Node *pNew;
    506         if (plibNode->type == XML_ELEMENT_NODE)
    507             pNew = new ElementNode(&elmRoot, this, plibNode);
    508         else if (plibNode->type == XML_TEXT_NODE)
    509             pNew = new ContentNode(this, plibNode);
    510         else
    511             continue;
    512         RTListAppend(&m_children, &pNew->m_childEntry);
    513 
    514         /* Recurse for this child element to get its own children. */
    515         pNew->buildChildren(elmRoot);
    516 #else
    517         boost::shared_ptr<Node> pNew;
    518 
    519         if (plibNode->type == XML_ELEMENT_NODE)
    520             pNew = boost::shared_ptr<Node>(new ElementNode(&elmRoot, this, plibNode));
    521         else if (plibNode->type == XML_TEXT_NODE)
    522             pNew = boost::shared_ptr<Node>(new ContentNode(this, plibNode));
    523         if (pNew)
    524         {
    525             // store
    526             m->children.push_back(pNew);
    527 
    528             // recurse for this child element to get its own children
    529             pNew->buildChildren(elmRoot);
    530         }
    531 #endif
    532     }
    533448}
    534449
     
    538453 * @return
    539454 */
    540 const char* Node::getName() const
     455const char *Node::getName() const
    541456{
    542457    return m_pcszName;
     
    548463 * @return
    549464 */
    550 const char* Node::getPrefix() const
     465const char *Node::getPrefix() const
    551466{
    552467    return m_pcszNamespacePrefix;
     
    558473 * @return
    559474 */
    560 const char* Node::getNamespaceURI() const
     475const char *Node::getNamespaceURI() const
    561476{
    562477    return m_pcszNamespaceHref;
     
    627542const char *Node::getValue() const
    628543{
    629     if (   m_plibAttr
    630         && m_plibAttr->children
     544    if (   m_pLibAttr
     545        && m_pLibAttr->children
    631546        )
    632547        // libxml hides attribute values in another node created as a
    633548        // single child of the attribute node, and it's in the content field
    634         return (const char *)m_plibAttr->children->content;
    635 
    636     if (   m_plibNode
    637         && m_plibNode->children)
    638         return (const char *)m_plibNode->children->content;
     549        return (const char *)m_pLibAttr->children->content;
     550
     551    if (   m_pLibNode
     552        && m_pLibNode->children)
     553        return (const char *)m_pLibNode->children->content;
    639554
    640555    return NULL;
     
    716631int Node::getLineNumber() const
    717632{
    718     if (m_plibAttr)
    719         return m_pParent->m_plibNode->line;
    720 
    721     return m_plibNode->line;
     633    if (m_pLibAttr)
     634        return m_pParent->m_pLibNode->line;
     635
     636    return m_pLibNode->line;
    722637}
    723638
    724639/**
    725640 * Private element constructor.
    726  * @param pelmRoot
    727  * @param pParent
    728  * @param plibNode
    729  */
    730 ElementNode::ElementNode(const ElementNode *pelmRoot,
     641 *
     642 * @param   pElmRoot    Pointer to the root element.
     643 * @param   pParent     Pointer to the parent element (always an ElementNode,
     644 *                      despite the type).  NULL for the root node.
     645 * @param   pListAnchor Pointer to the m_children member of the parent.  NULL
     646 *                      for the root node.
     647 * @param   pLibNode    Pointer to the libxml2 node structure.
     648 */
     649ElementNode::ElementNode(const ElementNode *pElmRoot,
    731650                         Node *pParent,
    732                          xmlNode *plibNode)
     651                         PRTLISTANCHOR pListAnchor,
     652                         xmlNode *pLibNode)
    733653    : Node(IsElement,
    734654           pParent,
    735            plibNode,
     655           pListAnchor,
     656           pLibNode,
    736657           NULL)
    737658{
    738     if (!(m_pelmRoot = pelmRoot))
    739         // NULL passed, then this is the root element
    740         m_pelmRoot = this;
    741 
    742     m_pcszName = (const char*)plibNode->name;
    743 
    744     if (plibNode->ns)
    745     {
    746         m_pcszNamespacePrefix = (const char*)m_plibNode->ns->prefix;
    747         m_pcszNamespaceHref = (const char*)m_plibNode->ns->href;
    748     }
    749 }
     659    m_pElmRoot = pElmRoot ? pElmRoot : this; // If NULL is passed, then this is the root element.
     660    m_pcszName = (const char *)pLibNode->name;
     661
     662    if (pLibNode->ns)
     663    {
     664        m_pcszNamespacePrefix = (const char *)m_pLibNode->ns->prefix;
     665        m_pcszNamespaceHref = (const char *)m_pLibNode->ns->href;
     666    }
     667
     668    RTListInit(&m_children);
     669    RTListInit(&m_attributes);
     670}
     671
     672ElementNode::~ElementNode()
     673{
     674    Node *pCur, *pNext;
     675    RTListForEachSafeCpp(&m_children, pCur, pNext, Node, m_listEntry)
     676    {
     677        delete pCur;
     678    }
     679    RTListInit(&m_children);
     680
     681    RTListForEachSafeCpp(&m_attributes, pCur, pNext, Node, m_listEntry)
     682    {
     683        delete pCur;
     684    }
     685    RTListInit(&m_attributes);
     686}
     687
     688
     689/**
     690 * Gets the next tree element in a full tree enumeration.
     691 *
     692 * @returns Pointer to the next element in the tree, NULL if we're done.
     693 * @param   pElmRoot            The root of the tree we're enumerating.  NULL if
     694 *                              it's the entire tree.
     695 */
     696ElementNode const *ElementNode::getNextTreeElement(ElementNode const *pElmRoot /*= NULL */) const
     697{
     698    /*
     699     * Consider children first.
     700     */
     701    ElementNode const *pChild = getFirstChildElement();
     702    if (pChild)
     703        return pChild;
     704
     705    /*
     706     * Then siblings, aunts and uncles.
     707     */
     708    ElementNode const *pCur = this;
     709    do
     710    {
     711        ElementNode const *pSibling = pCur->getNextSibilingElement();
     712        if (pSibling != NULL)
     713            return pSibling;
     714
     715        pCur = static_cast<const xml::ElementNode *>(pCur->m_pParent);
     716        Assert(pCur || pCur == pElmRoot);
     717    } while (pCur != pElmRoot);
     718
     719    return NULL;
     720}
     721
     722
     723/**
     724 * Private implementation.
     725 *
     726 * @param   pElmRoot        The root element.
     727 */
     728/*static*/ void ElementNode::buildChildren(ElementNode *pElmRoot)       // protected
     729{
     730    for (ElementNode *pCur = pElmRoot; pCur; pCur = pCur->getNextTreeElement(pElmRoot))
     731    {
     732        /*
     733         * Go thru this element's attributes creating AttributeNodes for them.
     734         */
     735        for (xmlAttr *pLibAttr = pCur->m_pLibNode->properties; pLibAttr; pLibAttr = pLibAttr->next)
     736        {
     737            AttributeNode *pNew = new AttributeNode(pElmRoot, pCur, &pCur->m_attributes, pLibAttr);
     738            RTListAppend(&pCur->m_attributes, &pNew->m_listEntry);
     739        }
     740
     741        /*
     742         * Go thru this element's child elements (element and text nodes).
     743         */
     744        for (xmlNodePtr pLibNode = pCur->m_pLibNode->children; pLibNode; pLibNode = pLibNode->next)
     745        {
     746            Node *pNew;
     747            if (pLibNode->type == XML_ELEMENT_NODE)
     748                pNew = new ElementNode(pElmRoot, pCur, &pCur->m_children, pLibNode);
     749            else if (pLibNode->type == XML_TEXT_NODE)
     750                pNew = new ContentNode(pCur, &pCur->m_children, pLibNode);
     751            else
     752                continue;
     753            RTListAppend(&pCur->m_children, &pNew->m_listEntry);
     754        }
     755    }
     756}
     757
    750758
    751759/**
     
    762770{
    763771    int i = 0;
    764 #ifndef USE_STD_LIST_FOR_CHILDREN
    765772    Node *p;
    766     RTListForEachCpp(&m_children, p, Node, m_childEntry)
    767 #else
    768     for (Data::InternalNodesList::iterator it = m->children.begin();
    769          it != m->children.end();
    770          ++it)
    771 #endif
     773    RTListForEachCpp(&m_children, p, Node, m_listEntry)
    772774    {
    773775        // export this child node if ...
    774 #ifdef USE_STD_LIST_FOR_CHILDREN
    775         Node *p = it->get();
    776 #endif
    777776        if (p->isElement())
    778777            if (   !pcszMatch                       // ... the caller wants all nodes or ...
     
    796795const ElementNode *ElementNode::findChildElement(const char *pcszNamespace, const char *pcszMatch) const
    797796{
    798 #ifndef USE_STD_LIST_FOR_CHILDREN
    799797    Node *p;
    800     RTListForEachCpp(&m_children, p, Node, m_childEntry)
     798    RTListForEachCpp(&m_children, p, Node, m_listEntry)
    801799    {
    802800        if (p->isElement())
     
    807805        }
    808806    }
    809 #else
    810     Data::InternalNodesList::const_iterator
    811         it,
    812         last = m->children.end();
    813     for (it = m->children.begin(); it != last; ++it)
    814         if ((**it).isElement())
    815         {
    816             ElementNode *pelm = static_cast<ElementNode*>((*it).get());
    817             if (pelm->nameEquals(pcszNamespace, pcszMatch))
    818                 return pelm;
    819         }
    820 #endif
    821 
    822807    return NULL;
    823808}
     
    828813 * @return child element or NULL if not found.
    829814 */
    830 const ElementNode * ElementNode::findChildElementFromId(const char *pcszId) const
    831 {
    832 #ifndef USE_STD_LIST_FOR_CHILDREN
    833     Node *p;
    834     RTListForEachCpp(&m_children, p, Node, m_childEntry)
     815const ElementNode *ElementNode::findChildElementFromId(const char *pcszId) const
     816{
     817    const Node *p;
     818    RTListForEachCpp(&m_children, p, Node, m_listEntry)
    835819    {
    836820        if (p->isElement())
    837821        {
    838             ElementNode *pelm = static_cast<ElementNode*>(p);
    839             const AttributeNode *pAttr = pelm->findAttribute("id");
     822            const ElementNode   *pElm  = static_cast<const ElementNode *>(p);
     823            const AttributeNode *pAttr = pElm->findAttribute("id");
    840824            if (pAttr && !strcmp(pAttr->getValue(), pcszId))
    841                 return pelm;
     825                return pElm;
    842826        }
    843827    }
    844 #else
    845     Data::InternalNodesList::const_iterator
    846         it,
    847         last = m->children.end();
    848     for (it = m->children.begin();
    849          it != last;
    850          ++it)
    851     {
    852         if ((**it).isElement())
    853         {
    854             ElementNode *pelm = static_cast<ElementNode*>((*it).get());
    855             const AttributeNode *pAttr;
    856             if (    ((pAttr = pelm->findAttribute("id")))
    857                  && (!strcmp(pAttr->getValue(), pcszId))
    858                )
    859                 return pelm;
    860         }
    861     }
    862 #endif
    863828    return NULL;
    864829}
     
    871836        return this->findChildElement(pcszNamespace, pcszPath);
    872837
    873 #ifndef USE_STD_LIST_FOR_CHILDREN
    874838    /** @todo Can be done without recursion as we have both sibling lists and parent
    875839     *        pointers in this variant.  */
    876     Node *p;
    877     RTListForEachCpp(&m_children, p, Node, m_childEntry)
     840    const Node *p;
     841    RTListForEachCpp(&m_children, p, Node, m_listEntry)
    878842    {
    879843        if (p->isElement())
    880844        {
    881             const ElementNode *pElm = static_cast<ElementNode*>(p);
     845            const ElementNode *pElm = static_cast<const ElementNode *>(p);
    882846            if (pElm->nameEqualsN(pcszNamespace, pcszPath, cchThis))
    883847            {
     
    888852        }
    889853    }
    890 #else
    891     Data::InternalNodesList::const_iterator  itLast = m->children.end();
    892     for (Data::InternalNodesList::const_iterator it = m->children.begin(); it != itLast; ++it)
    893     {
    894         if ((**it).isElement())
    895         {
    896             const ElementNode *pElm = static_cast<ElementNode*>((*it).get());
    897             if (pElm->nameEqualsN(pcszNamespace, pcszPath, cchThis))
    898             {
    899                 pElm = findChildElementP(pcszPath + cchThis, pcszNamespace);
    900                 if (pElm)
    901                     return pElm;
    902             }
    903         }
    904     }
    905 #endif
    906 
     854
     855    return NULL;
     856}
     857
     858const ElementNode *ElementNode::getFirstChildElement() const
     859{
     860    const Node *p;
     861    RTListForEachCpp(&m_children, p, Node, m_listEntry)
     862    {
     863        if (p->isElement())
     864            return static_cast<const ElementNode *>(p);
     865    }
     866    return NULL;
     867}
     868
     869const ElementNode *ElementNode::getLastChildElement() const
     870{
     871    const Node *p;
     872    RTListForEachReverseCpp(&m_children, p, Node, m_listEntry)
     873    {
     874        if (p->isElement())
     875            return static_cast<const ElementNode *>(p);
     876    }
    907877    return NULL;
    908878}
     
    915885    for (;;)
    916886    {
    917         pSibling = RTListGetPrevCpp(&m_pParent->m_children, pSibling, const Node, m_childEntry);
     887        pSibling = RTListGetPrevCpp(m_pParentListAnchor, pSibling, const Node, m_listEntry);
    918888        if (!pSibling)
    919889            return NULL;
     
    930900    for (;;)
    931901    {
    932         pSibling = RTListGetNextCpp(&m_pParent->m_children, pSibling, const Node, m_childEntry);
     902        pSibling = RTListGetNextCpp(m_pParentListAnchor, pSibling, const Node, m_listEntry);
    933903        if (!pSibling)
    934904            return NULL;
     
    945915    for (;;)
    946916    {
    947         pSibling = RTListGetPrevCpp(&m_pParent->m_children, pSibling, const Node, m_childEntry);
     917        pSibling = RTListGetPrevCpp(m_pParentListAnchor, pSibling, const Node, m_listEntry);
    948918        if (!pSibling)
    949919            return NULL;
     
    964934    for (;;)
    965935    {
    966         pSibling = RTListGetNextCpp(&m_pParent->m_children, pSibling, const Node, m_childEntry);
     936        pSibling = RTListGetNextCpp(m_pParentListAnchor, pSibling, const Node, m_listEntry);
    967937        if (!pSibling)
    968938            return NULL;
     
    998968 * @return
    999969 */
    1000 const AttributeNode* ElementNode::findAttribute(const char *pcszMatch) const
    1001 {
    1002     Data::AttributesMap::const_iterator it;
    1003 
    1004     it = m->attribs.find(pcszMatch);
    1005     if (it != m->attribs.end())
    1006         return it->second.get();
    1007 
     970const AttributeNode *ElementNode::findAttribute(const char *pcszMatch) const
     971{
     972    AttributeNode *p;
     973    RTListForEachCpp(&m_attributes, p, AttributeNode, m_listEntry)
     974    {
     975        if (p->nameEquals(pcszMatch))
     976            return p;
     977    }
    1008978    return NULL;
    1009979}
     
    1013983 * name and returns its value as a string.
    1014984 *
    1015  * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
    1016  * @param ppcsz out: attribute value
    1017  * @return TRUE if attribute was found and str was thus updated.
    1018  */
    1019 bool ElementNode::getAttributeValue(const char *pcszMatch, const char *&ppcsz) const
    1020 {
    1021     const Node* pAttr;
    1022     if ((pAttr = findAttribute(pcszMatch)))
    1023     {
    1024         ppcsz = pAttr->getValue();
     985 * @param   pcszMatch   Name of attribute to find (see findAttribute() for
     986 *                      namespace remarks).
     987 * @param   ppcsz       Where to return the attribute.
     988 * @returns Boolean success indicator.
     989 */
     990bool ElementNode::getAttributeValue(const char *pcszMatch, const char **ppcsz) const
     991{
     992    const AttributeNode *pAttr = findAttribute(pcszMatch);
     993    if (pAttr)
     994    {
     995        *ppcsz = pAttr->getValue();
    1025996        return true;
    1026997    }
    1027 
    1028998    return false;
    1029999}
     
    10331003 * name and returns its value as a string.
    10341004 *
    1035  * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
    1036  * @param str out: attribute value; overwritten only if attribute was found
    1037  * @return TRUE if attribute was found and str was thus updated.
    1038  */
    1039 bool ElementNode::getAttributeValue(const char *pcszMatch, RTCString &str) const
    1040 {
    1041     const Node* pAttr;
    1042     if ((pAttr = findAttribute(pcszMatch)))
    1043     {
    1044         str = pAttr->getValue();
     1005 * @param   pcszMatch   Name of attribute to find (see findAttribute() for
     1006 *                      namespace remarks).
     1007 * @param   rStr        Reference to the string object that should receive the
     1008 *                      attribute value.
     1009 * @returns Boolean success indicator.
     1010 *
     1011 * @throws  Whatever the string class may throw on assignment.
     1012 */
     1013bool ElementNode::getAttributeValue(const char *pcszMatch, RTCString &rStr) const
     1014{
     1015    const AttributeNode *pAttr = findAttribute(pcszMatch);
     1016    if (pAttr)
     1017    {
     1018        rStr = pAttr->getValue();
    10451019        return true;
    10461020    }
     
    11151089 * function returns no error.
    11161090 *
    1117  * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
    1118  * @param i out: attribute value
    1119  * @return TRUE if attribute was found and str was thus updated.
    1120  */
    1121 bool ElementNode::getAttributeValue(const char *pcszMatch, int64_t &i) const
    1122 {
    1123     const char *pcsz;
    1124     if (    (getAttributeValue(pcszMatch, pcsz))
    1125          && (VINF_SUCCESS == RTStrToInt64Ex(pcsz, NULL, 0, &i))
    1126        )
    1127         return true;
    1128 
     1091 * @param   pcszMatch   Name of attribute to find (see findAttribute() for
     1092 *                      namespace remarks).
     1093 * @param   i           Where to return the attribute value on success.
     1094 * @returns Boolean success indicator.
     1095 */
     1096bool ElementNode::getAttributeValue(const char *pcszMatch, int64_t *piValue) const
     1097{
     1098    const char *pcsz = findAttributeValue(pcszMatch);
     1099    if (pcsz)
     1100    {
     1101        int rc = RTStrToInt64Ex(pcsz, NULL, 0, piValue);
     1102        if (rc == VINF_SUCCESS)
     1103            return true;
     1104    }
    11291105    return false;
    11301106}
     
    11651141    if (getAttributeValue(pcszMatch, pcsz))
    11661142    {
    1167         if (    (!strcmp(pcsz, "true"))
    1168              || (!strcmp(pcsz, "yes"))
    1169              || (!strcmp(pcsz, "1"))
     1143        if (   !strcmp(pcsz, "true")
     1144            || !strcmp(pcsz, "yes")
     1145            || !strcmp(pcsz, "1")
    11701146           )
    11711147        {
     
    11731149            return true;
    11741150        }
    1175         if (    (!strcmp(pcsz, "false"))
    1176              || (!strcmp(pcsz, "no"))
    1177              || (!strcmp(pcsz, "0"))
     1151        if (   !strcmp(pcsz, "false")
     1152            || !strcmp(pcsz, "no")
     1153            || !strcmp(pcsz, "0")
    11781154           )
    11791155        {
     
    11861162}
    11871163
     1164
     1165bool ElementNode::getElementValue(int32_t *piValue) const
     1166{
     1167    const char *pszValue = getValue();
     1168    if (pszValue)
     1169    {
     1170        int rc = RTStrToInt32Ex(pszValue, NULL, 0, piValue);
     1171        if (rc == VINF_SUCCESS)
     1172            return true;
     1173    }
     1174    return false;
     1175}
     1176
     1177bool ElementNode::getElementValue(uint32_t *puValue) const
     1178{
     1179    const char *pszValue = getValue();
     1180    if (pszValue)
     1181    {
     1182        int rc = RTStrToUInt32Ex(pszValue, NULL, 0, puValue);
     1183        if (rc == VINF_SUCCESS)
     1184            return true;
     1185    }
     1186    return false;
     1187}
     1188
     1189bool ElementNode::getElementValue(int64_t *piValue) const
     1190{
     1191    const char *pszValue = getValue();
     1192    if (pszValue)
     1193    {
     1194        int rc = RTStrToInt64Ex(pszValue, NULL, 0, piValue);
     1195        if (rc == VINF_SUCCESS)
     1196            return true;
     1197    }
     1198    return false;
     1199}
     1200
     1201bool ElementNode::getElementValue(uint64_t *puValue) const
     1202{
     1203    const char *pszValue = getValue();
     1204    if (pszValue)
     1205    {
     1206        int rc = RTStrToUInt64Ex(pszValue, NULL, 0, puValue);
     1207        if (rc == VINF_SUCCESS)
     1208            return true;
     1209    }
     1210    return false;
     1211}
     1212
     1213bool ElementNode::getElementValue(bool *pfValue) const
     1214{
     1215    const char *pszValue = getValue();
     1216    if (pszValue)
     1217    {
     1218        if (   !strcmp(pszValue, "true")
     1219            || !strcmp(pszValue, "yes")
     1220            || !strcmp(pszValue, "1")
     1221           )
     1222        {
     1223            *pfValue = true;
     1224            return true;
     1225        }
     1226        if (   !strcmp(pszValue, "false")
     1227            || !strcmp(pszValue, "no")
     1228            || !strcmp(pszValue, "0")
     1229           )
     1230        {
     1231            *pfValue = true;
     1232            return true;
     1233        }
     1234    }
     1235    return false;
     1236}
     1237
     1238
    11881239/**
    11891240 * Creates a new child element node and appends it to the list
     
    11961247{
    11971248    // we must be an element, not an attribute
    1198     if (!m_plibNode)
     1249    if (!m_pLibNode)
    11991250        throw ENodeIsNotElement(RT_SRC_POS);
    12001251
    12011252    // libxml side: create new node
    1202     xmlNode *plibNode;
    1203     if (!(plibNode = xmlNewNode(NULL,        // namespace
     1253    xmlNode *pLibNode;
     1254    if (!(pLibNode = xmlNewNode(NULL,        // namespace
    12041255                                (const xmlChar*)pcszElementName)))
    12051256        throw std::bad_alloc();
    1206     xmlAddChild(m_plibNode, plibNode);
     1257    xmlAddChild(m_pLibNode, pLibNode);
    12071258
    12081259    // now wrap this in C++
    1209     ElementNode *p = new ElementNode(m_pelmRoot, this, plibNode);
    1210 #ifndef USE_STD_LIST_FOR_CHILDREN
    1211     RTListAppend(&m_children, &p->m_childEntry);
    1212 #else
    1213     boost::shared_ptr<ElementNode> pNew(p);
    1214     m->children.push_back(pNew);
    1215 #endif
     1260    ElementNode *p = new ElementNode(m_pElmRoot, this, &m_children, pLibNode);
     1261    RTListAppend(&m_children, &p->m_listEntry);
    12161262
    12171263    return p;
     
    12291275{
    12301276    // libxml side: create new node
    1231     xmlNode *plibNode = xmlNewText((const xmlChar*)pcszContent);
    1232     if (!plibNode)
     1277    xmlNode *pLibNode = xmlNewText((const xmlChar*)pcszContent);
     1278    if (!pLibNode)
    12331279        throw std::bad_alloc();
    1234     xmlAddChild(m_plibNode, plibNode);
     1280    xmlAddChild(m_pLibNode, pLibNode);
    12351281
    12361282    // now wrap this in C++
    1237     ContentNode *p = new ContentNode(this, plibNode);
    1238 #ifndef USE_STD_LIST_FOR_CHILDREN
    1239     RTListAppend(&m_children, &p->m_childEntry);
    1240 #else
    1241     boost::shared_ptr<ContentNode> pNew(p);
    1242     m->children.push_back(pNew);
    1243 #endif
     1283    ContentNode *p = new ContentNode(this, &m_children, pLibNode);
     1284    RTListAppend(&m_children, &p->m_listEntry);
    12441285
    12451286    return p;
     
    12531294 * that was either created or changed.
    12541295 *
    1255  * @param pcszName
    1256  * @param pcszValue
    1257  * @return
    1258  */
    1259 AttributeNode* ElementNode::setAttribute(const char *pcszName, const char *pcszValue)
    1260 {
    1261     AttributeNode *pattrReturn;
    1262     Data::AttributesMap::const_iterator it;
    1263 
    1264     it = m->attribs.find(pcszName);
    1265     if (it == m->attribs.end())
    1266     {
    1267         // libxml side: xmlNewProp creates an attribute
    1268         xmlAttr *plibAttr = xmlNewProp(m_plibNode, (xmlChar*)pcszName, (xmlChar*)pcszValue);
    1269 
    1270         // C++ side: create an attribute node around it
    1271         const char *pcszKey;
    1272         boost::shared_ptr<AttributeNode> pNew(new AttributeNode(*m_pelmRoot, this, plibAttr, &pcszKey));
    1273         // store
    1274         m->attribs[pcszKey] = pNew;
    1275         pattrReturn = pNew.get();
    1276     }
    1277     else
    1278     {
    1279         // overwrite existing libxml attribute node
    1280         xmlAttrPtr plibAttr = xmlSetProp(m_plibNode, (xmlChar*)pcszName, (xmlChar*)pcszValue);
    1281 
    1282         // and fix our existing C++ side around it
    1283         boost::shared_ptr<AttributeNode> pattr = it->second;
    1284         pattr->m_plibAttr = plibAttr;       // in case the xmlAttrPtr is different, I'm not sure
    1285 
    1286         pattrReturn = pattr.get();
    1287     }
    1288 
    1289     return pattrReturn;
    1290 
     1296 * @param   pcszName        The attribute name.
     1297 * @param   pcszValue       The attribute value.
     1298 * @return  Pointer to the attribute node that was created or modified.
     1299 */
     1300AttributeNode *ElementNode::setAttribute(const char *pcszName, const char *pcszValue)
     1301{
     1302    /*
     1303     * Do we already have an attribute and should we just update it?
     1304     */
     1305    AttributeNode *pAttr;
     1306    RTListForEachCpp(&m_attributes, pAttr, AttributeNode, m_listEntry)
     1307    {
     1308        if (pAttr->nameEquals(pcszName))
     1309        {
     1310            /* Overwrite existing libxml attribute node ... */
     1311            xmlAttrPtr pLibAttr = xmlSetProp(m_pLibNode, (xmlChar *)pcszName, (xmlChar *)pcszValue);
     1312
     1313            /* ... and update our C++ wrapper in case the attrib pointer changed. */
     1314            pAttr->m_pLibAttr = pLibAttr;
     1315            return pAttr;
     1316        }
     1317    }
     1318
     1319    /*
     1320     * No existing attribute, create a new one.
     1321     */
     1322    /* libxml side: xmlNewProp creates an attribute. */
     1323    xmlAttr *pLibAttr = xmlNewProp(m_pLibNode, (xmlChar *)pcszName, (xmlChar *)pcszValue);
     1324
     1325    /* C++ side: Create an attribute node around it. */
     1326    pAttr = new AttributeNode(m_pElmRoot, this, &m_attributes, pLibAttr);
     1327    RTListAppend(&m_attributes, &pAttr->m_listEntry);
     1328
     1329    return pAttr;
    12911330}
    12921331
     
    14171456
    14181457/**
    1419  * Private constructor for a new attribute node. This one is special:
    1420  * in ppcszKey, it returns a pointer to a string buffer that should be
    1421  * used to index the attribute correctly with namespaces.
    1422  *
    1423  * @param pParent
    1424  * @param elmRoot
    1425  * @param plibAttr
    1426  * @param ppcszKey
    1427  */
    1428 AttributeNode::AttributeNode(const ElementNode &elmRoot,
     1458 * Private constructor for a new attribute node.
     1459 *
     1460 * @param   pElmRoot    Pointer to the root element.  Needed for getting the
     1461 *                      default name space.
     1462 * @param   pParent     Pointer to the parent element (always an ElementNode,
     1463 *                      despite the type).  NULL for the root node.
     1464 * @param   pListAnchor Pointer to the m_children member of the parent.  NULL
     1465 *                      for the root node.
     1466 * @param   pLibNode    Pointer to the libxml2 node structure.
     1467 */
     1468AttributeNode::AttributeNode(const ElementNode *pElmRoot,
    14291469                             Node *pParent,
    1430                              xmlAttr *plibAttr,
    1431                              const char **ppcszKey)
     1470                             PRTLISTANCHOR pListAnchor,
     1471                             xmlAttr *pLibAttr)
    14321472    : Node(IsAttribute,
    14331473           pParent,
     1474           pListAnchor,
    14341475           NULL,
    1435            plibAttr)
    1436 {
    1437     m_pcszName = (const char*)plibAttr->name;
    1438 
    1439     *ppcszKey = m_pcszName;
    1440 
    1441     if (    plibAttr->ns
    1442          && plibAttr->ns->prefix
    1443        )
    1444     {
    1445         m_pcszNamespacePrefix = (const char*)plibAttr->ns->prefix;
    1446         m_pcszNamespaceHref = (const char*)plibAttr->ns->href;
    1447 
    1448         if (    !elmRoot.m_pcszNamespaceHref
    1449              || (strcmp(m_pcszNamespaceHref, elmRoot.m_pcszNamespaceHref))
    1450            )
     1476           pLibAttr)
     1477{
     1478    m_pcszName = (const char *)pLibAttr->name;
     1479
     1480    if (   pLibAttr->ns
     1481        && pLibAttr->ns->prefix)
     1482    {
     1483        m_pcszNamespacePrefix = (const char *)pLibAttr->ns->prefix;
     1484        m_pcszNamespaceHref   = (const char *)pLibAttr->ns->href;
     1485
     1486        if (   !pElmRoot->m_pcszNamespaceHref
     1487            || strcmp(m_pcszNamespaceHref, pElmRoot->m_pcszNamespaceHref))
    14511488        {
    14521489            // not default namespace:
     
    14541491            m_strKey.append(':');
    14551492            m_strKey.append(m_pcszName);
    1456 
    1457             *ppcszKey = m_strKey.c_str();
    14581493        }
    14591494    }
    14601495}
    14611496
    1462 ContentNode::ContentNode(Node *pParent, xmlNode *plibNode)
     1497ContentNode::ContentNode(Node *pParent, PRTLISTANCHOR pListAnchor, xmlNode *pLibNode)
    14631498    : Node(IsContent,
    14641499           pParent,
    1465            plibNode,
     1500           pListAnchor,
     1501           pLibNode,
    14661502           NULL)
    14671503{
     
    16011637void Document::refreshInternals() // private
    16021638{
    1603     m->pRootElement = new ElementNode(NULL, NULL, xmlDocGetRootElement(m->plibDocument));
    1604 
    1605     m->pRootElement->buildChildren(*m->pRootElement);
     1639    m->pRootElement = new ElementNode(NULL, NULL, NULL, xmlDocGetRootElement(m->plibDocument));
     1640
     1641    ElementNode::buildChildren(m->pRootElement);
    16061642}
    16071643
     
    16111647 * @return
    16121648 */
    1613 const ElementNode* Document::getRootElement() const
     1649const ElementNode *Document::getRootElement() const
    16141650{
    16151651    return m->pRootElement;
     
    16211657 * @return
    16221658 */
    1623 ElementNode* Document::getRootElement()
     1659ElementNode *Document::getRootElement()
    16241660{
    16251661    return m->pRootElement;
     
    16271663
    16281664/**
    1629  * Creates a new element node and sets it as the root element. This will
    1630  * only work if the document is empty; otherwise EDocumentNotEmpty is thrown.
    1631  */
    1632 ElementNode* Document::createRootElement(const char *pcszRootElementName,
     1665 * Creates a new element node and sets it as the root element.
     1666 *
     1667 * This will only work if the document is empty; otherwise EDocumentNotEmpty is
     1668 * thrown.
     1669 */
     1670ElementNode *Document::createRootElement(const char *pcszRootElementName,
    16331671                                         const char *pcszComment /* = NULL */)
    16341672{
     
    16371675
    16381676    // libxml side: create document, create root node
    1639     m->plibDocument = xmlNewDoc((const xmlChar*)"1.0");
    1640     xmlNode *plibRootNode;
    1641     if (!(plibRootNode = xmlNewNode(NULL,        // namespace
    1642                                     (const xmlChar*)pcszRootElementName)))
     1677    m->plibDocument = xmlNewDoc((const xmlChar *)"1.0");
     1678    xmlNode *plibRootNode = xmlNewNode(NULL /*namespace*/ , (const xmlChar *)pcszRootElementName);
     1679    if (!plibRootNode)
    16431680        throw std::bad_alloc();
    16441681    xmlDocSetRootElement(m->plibDocument, plibRootNode);
     1682
    16451683    // now wrap this in C++
    1646     m->pRootElement = new ElementNode(NULL, NULL, plibRootNode);
     1684    m->pRootElement = new ElementNode(NULL, NULL, NULL, plibRootNode);
    16471685
    16481686    // add document global comment if specified
    16491687    if (pcszComment != NULL)
    16501688    {
    1651         xmlNode *pComment;
    1652         if (!(pComment = xmlNewDocComment(m->plibDocument,
    1653                                           (const xmlChar *)pcszComment)))
     1689        xmlNode *pComment = xmlNewDocComment(m->plibDocument, (const xmlChar *)pcszComment);
     1690        if (!pComment)
    16541691            throw std::bad_alloc();
    16551692        xmlAddPrevSibling(plibRootNode, pComment);
     1693
    16561694        // now wrap this in C++
    1657         m->pComment = new ElementNode(NULL, NULL, pComment);
     1695        m->pComment = new ElementNode(NULL, NULL, NULL, pComment);
    16581696    }
    16591697
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