Changeset 48779 in vbox for trunk/src/VBox/Runtime/r3/xml.cpp
- Timestamp:
- Oct 1, 2013 2:14:13 AM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 89417
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/xml.cpp
r46169 r48779 5 5 6 6 /* 7 * Copyright (C) 2007-201 2Oracle Corporation7 * Copyright (C) 2007-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 25 25 */ 26 26 27 28 /******************************************************************************* 29 * Header Files * 30 *******************************************************************************/ 27 31 #include <iprt/dir.h> 28 32 #include <iprt/file.h> … … 43 47 44 48 #include <map> 45 #include <boost/shared_ptr.hpp> 46 47 //////////////////////////////////////////////////////////////////////////////// 48 // 49 // globals 50 // 51 //////////////////////////////////////////////////////////////////////////////// 52 49 #include <boost/shared_ptr.hpp> /* This is the ONLY use of boost. */ 50 51 52 /******************************************************************************* 53 * Global Variables * 54 *******************************************************************************/ 53 55 /** 54 56 * Global module initialization structure. This is to wrap non-reentrant bits … … 59 61 * this structure. 60 62 */ 61 static 62 class Global 63 static class Global 63 64 { 64 65 public: … … 94 95 } 95 96 sxml; /* XXX naming this xml will break with gcc-3.3 */ 96 } 97 gGlobal; 97 } gGlobal; 98 98 99 99 … … 132 132 * returned string using RTStrFree() when no more necessary. 133 133 */ 134 // static 135 char *XmlError::Format(xmlErrorPtr aErr) 134 /* static */ char *XmlError::Format(xmlErrorPtr aErr) 136 135 { 137 136 const char *msg = aErr->message ? aErr->message : "<none>"; … … 443 442 AttributesMap attribs; 444 443 444 #ifdef USE_STD_LIST_FOR_CHILDREN 445 445 // child elements, if this is an element; can be empty 446 446 typedef std::list< boost::shared_ptr<Node> > InternalNodesList; 447 447 InternalNodesList children; 448 #endif 448 449 }; 449 450 … … 452 453 xmlNode *plibNode, 453 454 xmlAttr *plibAttr) 454 : m_Type(type), 455 m_pParent(pParent), 456 m_plibNode(plibNode), 457 m_plibAttr(plibAttr), 458 m_pcszNamespacePrefix(NULL), 459 m_pcszNamespaceHref(NULL), 460 m_pcszName(NULL), 461 m(new Data) 462 { 455 : m_Type(type) 456 , m_pParent(pParent) 457 , m_plibNode(plibNode) 458 , m_plibAttr(plibAttr) 459 , m_pcszNamespacePrefix(NULL) 460 , m_pcszNamespaceHref(NULL) 461 , 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 463 468 } 464 469 465 470 Node::~Node() 466 471 { 472 #ifndef USE_STD_LIST_FOR_CHILDREN 473 Node *pCur, *pNext; 474 RTListForEachSafe(&m_children, pCur, pNext, Node, m_childEntry) 475 { 476 delete pCur; 477 } 478 RTListInit(&m_children); 479 #endif 467 480 delete m; 468 481 } … … 487 500 488 501 // go thru this element's child elements 489 xmlNodePtr plibNode = m_plibNode->children; 490 while (plibNode) 491 { 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 492 517 boost::shared_ptr<Node> pNew; 493 518 … … 504 529 pNew->buildChildren(elmRoot); 505 530 } 506 507 plibNode = plibNode->next; 531 #endif 508 532 } 509 533 } … … 567 591 568 592 /** 593 * Variant of nameEquals that checks the namespace as well. 594 * 595 * @return true if equal, false if not. 596 * @param pcszNamespace The name space prefix or NULL. 597 * @param pcsz The element name. 598 * @param cchMax The maximum number of character from @a pcsz to 599 * match. 600 */ 601 bool Node::nameEqualsN(const char *pcszNamespace, const char *pcsz, size_t cchMax) const 602 { 603 /* Match the name. */ 604 if (!m_pcszName) 605 return false; 606 if (!pcsz || cchMax == 0) 607 return false; 608 if (strncmp(m_pcszName, pcsz, cchMax)) 609 return false; 610 if (strlen(m_pcszName) > cchMax) 611 return false; 612 613 /* Match name space. */ 614 if (!pcszNamespace) 615 return true; /* NULL, anything goes. */ 616 if (!m_pcszNamespacePrefix) 617 return false; /* Element has no namespace. */ 618 return !strcmp(m_pcszNamespacePrefix, pcszNamespace); 619 } 620 621 /** 569 622 * Returns the value of a node. If this node is an attribute, returns 570 623 * the attribute value; if this node is an element, then this returns … … 572 625 * @return 573 626 */ 574 const char *Node::getValue() const575 { 576 if ( (m_plibAttr)577 && (m_plibAttr->children)578 )627 const char *Node::getValue() const 628 { 629 if ( m_plibAttr 630 && m_plibAttr->children 631 ) 579 632 // libxml hides attribute values in another node created as a 580 633 // single child of the attribute node, and it's in the content field 581 return (const char*)m_plibAttr->children->content; 582 583 if ( (m_plibNode) 584 && (m_plibNode->children) 585 ) 586 return (const char*)m_plibNode->children->content; 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; 587 639 588 640 return NULL; … … 710 762 { 711 763 int i = 0; 764 #ifndef USE_STD_LIST_FOR_CHILDREN 765 Node *p; 766 RTListForEach(&m_children, p, Node, m_childEntry) 767 #else 712 768 for (Data::InternalNodesList::iterator it = m->children.begin(); 713 769 it != m->children.end(); 714 770 ++it) 771 #endif 715 772 { 716 773 // export this child node if ... 774 #ifdef USE_STD_LIST_FOR_CHILDREN 717 775 Node *p = it->get(); 776 #endif 718 777 if (p->isElement()) 719 if ( (!pcszMatch) // the caller wants all nodes or720 || (!strcmp(pcszMatch, p->getName())) // the element name matches778 if ( !pcszMatch // ... the caller wants all nodes or ... 779 || !strcmp(pcszMatch, p->getName()) // ... the element name matches. 721 780 ) 722 781 { 723 children.push_back(static_cast<ElementNode *>(p));782 children.push_back(static_cast<ElementNode *>(p)); 724 783 ++i; 725 784 } … … 735 794 * @return 736 795 */ 737 const ElementNode* ElementNode::findChildElement(const char *pcszNamespace, 738 const char *pcszMatch) 739 const 740 { 796 const ElementNode *ElementNode::findChildElement(const char *pcszNamespace, const char *pcszMatch) const 797 { 798 #ifndef USE_STD_LIST_FOR_CHILDREN 799 Node *p; 800 RTListForEach(&m_children, p, Node, m_childEntry) 801 { 802 if (p->isElement()) 803 { 804 ElementNode *pelm = static_cast<ElementNode*>(p); 805 if (pelm->nameEquals(pcszNamespace, pcszMatch)) 806 return pelm; 807 } 808 } 809 #else 741 810 Data::InternalNodesList::const_iterator 742 811 it, 743 812 last = m->children.end(); 744 for (it = m->children.begin(); 745 it != last; 746 ++it) 747 { 813 for (it = m->children.begin(); it != last; ++it) 748 814 if ((**it).isElement()) 749 815 { … … 752 818 return pelm; 753 819 } 754 } 820 #endif 755 821 756 822 return NULL; … … 762 828 * @return child element or NULL if not found. 763 829 */ 764 const ElementNode* ElementNode::findChildElementFromId(const char *pcszId) const 765 { 830 const ElementNode * ElementNode::findChildElementFromId(const char *pcszId) const 831 { 832 #ifndef USE_STD_LIST_FOR_CHILDREN 833 Node *p; 834 RTListForEach(&m_children, p, Node, m_childEntry) 835 { 836 if (p->isElement()) 837 { 838 ElementNode *pelm = static_cast<ElementNode*>(p); 839 const AttributeNode *pAttr = pelm->findAttribute("id"); 840 if (pAttr && !strcmp(pAttr->getValue(), pcszId)) 841 return pelm; 842 } 843 } 844 #else 766 845 Data::InternalNodesList::const_iterator 767 846 it, … … 781 860 } 782 861 } 862 #endif 863 return NULL; 864 } 865 866 /** 867 * Recursively find the first matching child element. 868 * 869 * @returns child element or NULL if not found. 870 * @param pcszNamespace The Namespace prefix or NULL. 871 * @param pcszPath Simple element path, with parent and child elements 872 * separated by a forward slash ('/'). 873 */ 874 const ElementNode *ElementNode::findChildElementDeep(const char *pcszNamespace, const char *pcszPath) const 875 { 876 size_t cchThis = strchr(pcszPath, '/') - pcszPath; 877 if (cchThis == (const char *)0 - pcszPath) 878 return this->findChildElement(pcszNamespace, pcszPath); 879 880 #ifndef USE_STD_LIST_FOR_CHILDREN 881 /** @todo Can be done without recursion as we have both sibling lists and parent 882 * pointers in this variant. */ 883 Node *p; 884 RTListForEach(&m_children, p, Node, m_childEntry) 885 { 886 if (p->isElement()) 887 { 888 const ElementNode *pElm = static_cast<ElementNode*>(p); 889 if (pElm->nameEqualsN(pcszNamespace, pcszPath, cchThis)) 890 { 891 pElm = findChildElementDeep(pcszNamespace, pcszPath + cchThis); 892 if (pElm) 893 return pElm; 894 } 895 } 896 } 897 #else 898 Data::InternalNodesList::const_iterator itLast = m->children.end(); 899 for (Data::InternalNodesList::const_iterator it = m->children.begin(); it != itLast; ++it) 900 { 901 if ((**it).isElement()) 902 { 903 const ElementNode *pElm = static_cast<ElementNode*>((*it).get()); 904 if (pElm->nameEqualsN(pcszNamespace, pcszPath, cchThis)) 905 { 906 pElm = findChildElementDeep(pcszNamespace, pcszPath + cchThis); 907 if (pElm) 908 return pElm; 909 } 910 } 911 } 912 #endif 783 913 784 914 return NULL; … … 1001 1131 * @return 1002 1132 */ 1003 ElementNode *ElementNode::createChild(const char *pcszElementName)1133 ElementNode *ElementNode::createChild(const char *pcszElementName) 1004 1134 { 1005 1135 // we must be an element, not an attribute … … 1016 1146 // now wrap this in C++ 1017 1147 ElementNode *p = new ElementNode(m_pelmRoot, this, plibNode); 1148 #ifndef USE_STD_LIST_FOR_CHILDREN 1149 RTListAppend(&m_children, &p->m_childEntry); 1150 #else 1018 1151 boost::shared_ptr<ElementNode> pNew(p); 1019 1152 m->children.push_back(pNew); 1153 #endif 1020 1154 1021 1155 return p; … … 1030 1164 * @return 1031 1165 */ 1032 ContentNode *ElementNode::addContent(const char *pcszContent)1166 ContentNode *ElementNode::addContent(const char *pcszContent) 1033 1167 { 1034 1168 // libxml side: create new node 1035 xmlNode *plibNode ;1036 if (! (plibNode = xmlNewText((const xmlChar*)pcszContent)))1169 xmlNode *plibNode = xmlNewText((const xmlChar*)pcszContent); 1170 if (!plibNode) 1037 1171 throw std::bad_alloc(); 1038 1172 xmlAddChild(m_plibNode, plibNode); … … 1040 1174 // now wrap this in C++ 1041 1175 ContentNode *p = new ContentNode(this, plibNode); 1176 #ifndef USE_STD_LIST_FOR_CHILDREN 1177 RTListAppend(&m_children, &p->m_childEntry); 1178 #else 1042 1179 boost::shared_ptr<ContentNode> pNew(p); 1043 1180 m->children.push_back(pNew); 1181 #endif 1044 1182 1045 1183 return p; … … 1501 1639 * The document that is passed in will be reset before being filled if not empty. 1502 1640 * 1503 * @param pvBuf in: memory buffer to parse. 1504 * @param cbSize in: size of the memory buffer. 1505 * @param strFilename in: name fo file to parse. 1506 * @param doc out: document to be reset and filled with data according to file contents. 1507 */ 1508 void XmlMemParser::read(const void* pvBuf, size_t cbSize, 1641 * @param pvBuf Memory buffer to parse. 1642 * @param cbSize Size of the memory buffer. 1643 * @param strFilename Refernece to the name of the file we're parsing. 1644 * @param doc Reference to the output document. This will be reset 1645 * and filled with data according to file contents. 1646 */ 1647 void XmlMemParser::read(const void *pvBuf, size_t cbSize, 1509 1648 const RTCString &strFilename, 1510 1649 Document &doc)
Note:
See TracChangeset
for help on using the changeset viewer.