VirtualBox

Changeset 48834 in vbox for trunk/src/VBox/Runtime


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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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