Changeset 48834 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Oct 3, 2013 1:28:57 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/xml.cpp
r48797 r48834 47 47 48 48 #include <map> 49 #include <boost/shared_ptr.hpp> /* This is the ONLY use of boost. */50 49 51 50 … … 156 155 RTStrAPrintfV(&pszContext2, pcszContext, args); 157 156 char *newMsg; 158 RTStrAPrintf(&newMsg, "%s: %d 157 RTStrAPrintf(&newMsg, "%s: %d(%s)", pszContext2, aRC, RTErrGetShort(aRC)); 159 158 setWhat(newMsg); 160 159 RTStrFree(newMsg); … … 241 240 } 242 241 243 const char *File::uri() const242 const char *File::uri() const 244 243 { 245 244 return m->strFileName.c_str(); … … 291 290 { 292 291 size_t len = aLen; 293 int vrc = RTFileWrite 294 if (RT_SUCCESS 292 int vrc = RTFileWrite(m->handle, aBuf, len, &len); 293 if (RT_SUCCESS(vrc)) 295 294 return (int)len; 296 295 297 296 throw EIPRTFailure(vrc, "Runtime error writing to file '%s'", m->strFileName.c_str()); 298 299 return -1 /* failure */;300 297 } 301 298 302 299 void File::truncate() 303 300 { 304 int vrc = RTFileSetSize 305 if (RT_SUCCESS 301 int vrc = RTFileSetSize(m->handle, pos()); 302 if (RT_SUCCESS(vrc)) 306 303 return; 307 304 … … 318 315 { 319 316 Data() 320 : buf (NULL), len (0), uri (NULL), pos(0) {}317 : buf(NULL), len(0), uri(NULL), pos(0) {} 321 318 322 319 const char *buf; … … 327 324 }; 328 325 329 MemoryBuf::MemoryBuf 330 : m 326 MemoryBuf::MemoryBuf(const char *aBuf, size_t aLen, const char *aURI /* = NULL */) 327 : m(new Data()) 331 328 { 332 329 if (aBuf == NULL) 333 throw EInvalidArg 330 throw EInvalidArg(RT_SRC_POS); 334 331 335 332 m->buf = aBuf; 336 333 m->len = aLen; 337 m->uri = RTStrDup 334 m->uri = RTStrDup(aURI); 338 335 } 339 336 340 337 MemoryBuf::~MemoryBuf() 341 338 { 342 RTStrFree 339 RTStrFree(m->uri); 343 340 } 344 341 … … 353 350 } 354 351 355 void MemoryBuf::setPos 356 { 357 size_t off = (size_t) 352 void MemoryBuf::setPos(uint64_t aPos) 353 { 354 size_t off = (size_t)aPos; 358 355 if ((uint64_t) off != aPos) 359 356 throw EInvalidArg(); … … 365 362 } 366 363 367 int MemoryBuf::read 364 int MemoryBuf::read(char *aBuf, int aLen) 368 365 { 369 366 if (m->pos >= m->len) … … 371 368 372 369 size_t len = m->pos + aLen < m->len ? aLen : m->len - m->pos; 373 memcpy 370 memcpy(aBuf, m->buf + m->pos, len); 374 371 m->pos += len; 375 372 … … 422 419 } 423 420 421 422 424 423 //////////////////////////////////////////////////////////////////////////////// 425 424 // … … 427 426 // 428 427 //////////////////////////////////////////////////////////////////////////////// 429 430 struct Node::Data431 {432 struct compare_const_char433 {434 bool operator()(const char* s1, const char* s2) const435 {436 return strcmp(s1, s2) < 0;437 }438 };439 440 // attributes, if this is an element; can be empty441 typedef std::map<const char*, boost::shared_ptr<AttributeNode>, compare_const_char > AttributesMap;442 AttributesMap attribs;443 444 #ifdef USE_STD_LIST_FOR_CHILDREN445 // child elements, if this is an element; can be empty446 typedef std::list< boost::shared_ptr<Node> > InternalNodesList;447 InternalNodesList children;448 #endif449 };450 428 451 429 Node::Node(EnumType type, 452 430 Node *pParent, 453 xmlNode *plibNode, 454 xmlAttr *plibAttr) 431 PRTLISTANCHOR pListAnchor, 432 xmlNode *pLibNode, 433 xmlAttr *pLibAttr) 455 434 : m_Type(type) 456 435 , m_pParent(pParent) 457 , m_p libNode(plibNode)458 , m_p libAttr(plibAttr)436 , m_pLibNode(pLibNode) 437 , m_pLibAttr(pLibAttr) 459 438 , m_pcszNamespacePrefix(NULL) 460 439 , m_pcszNamespaceHref(NULL) 461 440 , 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); 468 444 } 469 445 470 446 Node::~Node() 471 447 { 472 #ifndef USE_STD_LIST_FOR_CHILDREN473 Node *pCur, *pNext;474 RTListForEachSafeCpp(&m_children, pCur, pNext, Node, m_childEntry)475 {476 delete pCur;477 }478 RTListInit(&m_children);479 #endif480 delete m;481 }482 483 /**484 * Private implementation.485 * @param elmRoot486 */487 void Node::buildChildren(const ElementNode &elmRoot) // private488 {489 // go thru this element's attributes490 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 // store496 m->attribs[pcszKey] = pNew;497 498 plibAttr = plibAttr->next;499 }500 501 // go thru this element's child elements502 for (xmlNodePtr plibNode = m_plibNode->children; plibNode; plibNode = plibNode->next)503 {504 #ifndef USE_STD_LIST_FOR_CHILDREN505 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 else511 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 #else517 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 // store526 m->children.push_back(pNew);527 528 // recurse for this child element to get its own children529 pNew->buildChildren(elmRoot);530 }531 #endif532 }533 448 } 534 449 … … 538 453 * @return 539 454 */ 540 const char *Node::getName() const455 const char *Node::getName() const 541 456 { 542 457 return m_pcszName; … … 548 463 * @return 549 464 */ 550 const char *Node::getPrefix() const465 const char *Node::getPrefix() const 551 466 { 552 467 return m_pcszNamespacePrefix; … … 558 473 * @return 559 474 */ 560 const char *Node::getNamespaceURI() const475 const char *Node::getNamespaceURI() const 561 476 { 562 477 return m_pcszNamespaceHref; … … 627 542 const char *Node::getValue() const 628 543 { 629 if ( m_p libAttr630 && m_p libAttr->children544 if ( m_pLibAttr 545 && m_pLibAttr->children 631 546 ) 632 547 // libxml hides attribute values in another node created as a 633 548 // single child of the attribute node, and it's in the content field 634 return (const char *)m_p libAttr->children->content;635 636 if ( m_p libNode637 && m_p libNode->children)638 return (const char *)m_p libNode->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; 639 554 640 555 return NULL; … … 716 631 int Node::getLineNumber() const 717 632 { 718 if (m_p libAttr)719 return m_pParent->m_p libNode->line;720 721 return m_p libNode->line;633 if (m_pLibAttr) 634 return m_pParent->m_pLibNode->line; 635 636 return m_pLibNode->line; 722 637 } 723 638 724 639 /** 725 640 * 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 */ 649 ElementNode::ElementNode(const ElementNode *pElmRoot, 731 650 Node *pParent, 732 xmlNode *plibNode) 651 PRTLISTANCHOR pListAnchor, 652 xmlNode *pLibNode) 733 653 : Node(IsElement, 734 654 pParent, 735 plibNode, 655 pListAnchor, 656 pLibNode, 736 657 NULL) 737 658 { 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 672 ElementNode::~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 */ 696 ElementNode 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 750 758 751 759 /** … … 762 770 { 763 771 int i = 0; 764 #ifndef USE_STD_LIST_FOR_CHILDREN765 772 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) 772 774 { 773 775 // export this child node if ... 774 #ifdef USE_STD_LIST_FOR_CHILDREN775 Node *p = it->get();776 #endif777 776 if (p->isElement()) 778 777 if ( !pcszMatch // ... the caller wants all nodes or ... … … 796 795 const ElementNode *ElementNode::findChildElement(const char *pcszNamespace, const char *pcszMatch) const 797 796 { 798 #ifndef USE_STD_LIST_FOR_CHILDREN799 797 Node *p; 800 RTListForEachCpp(&m_children, p, Node, m_ childEntry)798 RTListForEachCpp(&m_children, p, Node, m_listEntry) 801 799 { 802 800 if (p->isElement()) … … 807 805 } 808 806 } 809 #else810 Data::InternalNodesList::const_iterator811 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 #endif821 822 807 return NULL; 823 808 } … … 828 813 * @return child element or NULL if not found. 829 814 */ 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) 815 const ElementNode *ElementNode::findChildElementFromId(const char *pcszId) const 816 { 817 const Node *p; 818 RTListForEachCpp(&m_children, p, Node, m_listEntry) 835 819 { 836 820 if (p->isElement()) 837 821 { 838 ElementNode *pelm = static_cast<ElementNode*>(p);839 const AttributeNode *pAttr = p elm->findAttribute("id");822 const ElementNode *pElm = static_cast<const ElementNode *>(p); 823 const AttributeNode *pAttr = pElm->findAttribute("id"); 840 824 if (pAttr && !strcmp(pAttr->getValue(), pcszId)) 841 return p elm;825 return pElm; 842 826 } 843 827 } 844 #else845 Data::InternalNodesList::const_iterator846 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 #endif863 828 return NULL; 864 829 } … … 871 836 return this->findChildElement(pcszNamespace, pcszPath); 872 837 873 #ifndef USE_STD_LIST_FOR_CHILDREN874 838 /** @todo Can be done without recursion as we have both sibling lists and parent 875 839 * 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) 878 842 { 879 843 if (p->isElement()) 880 844 { 881 const ElementNode *pElm = static_cast< ElementNode*>(p);845 const ElementNode *pElm = static_cast<const ElementNode *>(p); 882 846 if (pElm->nameEqualsN(pcszNamespace, pcszPath, cchThis)) 883 847 { … … 888 852 } 889 853 } 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 858 const 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 869 const 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 } 907 877 return NULL; 908 878 } … … 915 885 for (;;) 916 886 { 917 pSibling = RTListGetPrevCpp( &m_pParent->m_children, pSibling, const Node, m_childEntry);887 pSibling = RTListGetPrevCpp(m_pParentListAnchor, pSibling, const Node, m_listEntry); 918 888 if (!pSibling) 919 889 return NULL; … … 930 900 for (;;) 931 901 { 932 pSibling = RTListGetNextCpp( &m_pParent->m_children, pSibling, const Node, m_childEntry);902 pSibling = RTListGetNextCpp(m_pParentListAnchor, pSibling, const Node, m_listEntry); 933 903 if (!pSibling) 934 904 return NULL; … … 945 915 for (;;) 946 916 { 947 pSibling = RTListGetPrevCpp( &m_pParent->m_children, pSibling, const Node, m_childEntry);917 pSibling = RTListGetPrevCpp(m_pParentListAnchor, pSibling, const Node, m_listEntry); 948 918 if (!pSibling) 949 919 return NULL; … … 964 934 for (;;) 965 935 { 966 pSibling = RTListGetNextCpp( &m_pParent->m_children, pSibling, const Node, m_childEntry);936 pSibling = RTListGetNextCpp(m_pParentListAnchor, pSibling, const Node, m_listEntry); 967 937 if (!pSibling) 968 938 return NULL; … … 998 968 * @return 999 969 */ 1000 const AttributeNode *ElementNode::findAttribute(const char *pcszMatch) const1001 { 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 970 const 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 } 1008 978 return NULL; 1009 979 } … … 1013 983 * name and returns its value as a string. 1014 984 * 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 */ 990 bool ElementNode::getAttributeValue(const char *pcszMatch, const char **ppcsz) const 991 { 992 const AttributeNode *pAttr = findAttribute(pcszMatch); 993 if (pAttr) 994 { 995 *ppcsz = pAttr->getValue(); 1025 996 return true; 1026 997 } 1027 1028 998 return false; 1029 999 } … … 1033 1003 * name and returns its value as a string. 1034 1004 * 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 */ 1013 bool ElementNode::getAttributeValue(const char *pcszMatch, RTCString &rStr) const 1014 { 1015 const AttributeNode *pAttr = findAttribute(pcszMatch); 1016 if (pAttr) 1017 { 1018 rStr = pAttr->getValue(); 1045 1019 return true; 1046 1020 } … … 1115 1089 * function returns no error. 1116 1090 * 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 */ 1096 bool 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 } 1129 1105 return false; 1130 1106 } … … 1165 1141 if (getAttributeValue(pcszMatch, pcsz)) 1166 1142 { 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") 1170 1146 ) 1171 1147 { … … 1173 1149 return true; 1174 1150 } 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") 1178 1154 ) 1179 1155 { … … 1186 1162 } 1187 1163 1164 1165 bool 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 1177 bool 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 1189 bool 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 1201 bool 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 1213 bool 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 1188 1239 /** 1189 1240 * Creates a new child element node and appends it to the list … … 1196 1247 { 1197 1248 // we must be an element, not an attribute 1198 if (!m_p libNode)1249 if (!m_pLibNode) 1199 1250 throw ENodeIsNotElement(RT_SRC_POS); 1200 1251 1201 1252 // libxml side: create new node 1202 xmlNode *p libNode;1203 if (!(p libNode = xmlNewNode(NULL, // namespace1253 xmlNode *pLibNode; 1254 if (!(pLibNode = xmlNewNode(NULL, // namespace 1204 1255 (const xmlChar*)pcszElementName))) 1205 1256 throw std::bad_alloc(); 1206 xmlAddChild(m_p libNode, plibNode);1257 xmlAddChild(m_pLibNode, pLibNode); 1207 1258 1208 1259 // 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); 1216 1262 1217 1263 return p; … … 1229 1275 { 1230 1276 // libxml side: create new node 1231 xmlNode *p libNode = xmlNewText((const xmlChar*)pcszContent);1232 if (!p libNode)1277 xmlNode *pLibNode = xmlNewText((const xmlChar*)pcszContent); 1278 if (!pLibNode) 1233 1279 throw std::bad_alloc(); 1234 xmlAddChild(m_p libNode, plibNode);1280 xmlAddChild(m_pLibNode, pLibNode); 1235 1281 1236 1282 // 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); 1244 1285 1245 1286 return p; … … 1253 1294 * that was either created or changed. 1254 1295 * 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 */ 1300 AttributeNode *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; 1291 1330 } 1292 1331 … … 1417 1456 1418 1457 /** 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 */ 1468 AttributeNode::AttributeNode(const ElementNode *pElmRoot, 1429 1469 Node *pParent, 1430 xmlAttr *plibAttr,1431 const char **ppcszKey)1470 PRTLISTANCHOR pListAnchor, 1471 xmlAttr *pLibAttr) 1432 1472 : Node(IsAttribute, 1433 1473 pParent, 1474 pListAnchor, 1434 1475 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)) 1451 1488 { 1452 1489 // not default namespace: … … 1454 1491 m_strKey.append(':'); 1455 1492 m_strKey.append(m_pcszName); 1456 1457 *ppcszKey = m_strKey.c_str();1458 1493 } 1459 1494 } 1460 1495 } 1461 1496 1462 ContentNode::ContentNode(Node *pParent, xmlNode *plibNode)1497 ContentNode::ContentNode(Node *pParent, PRTLISTANCHOR pListAnchor, xmlNode *pLibNode) 1463 1498 : Node(IsContent, 1464 1499 pParent, 1465 plibNode, 1500 pListAnchor, 1501 pLibNode, 1466 1502 NULL) 1467 1503 { … … 1601 1637 void Document::refreshInternals() // private 1602 1638 { 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); 1606 1642 } 1607 1643 … … 1611 1647 * @return 1612 1648 */ 1613 const ElementNode *Document::getRootElement() const1649 const ElementNode *Document::getRootElement() const 1614 1650 { 1615 1651 return m->pRootElement; … … 1621 1657 * @return 1622 1658 */ 1623 ElementNode *Document::getRootElement()1659 ElementNode *Document::getRootElement() 1624 1660 { 1625 1661 return m->pRootElement; … … 1627 1663 1628 1664 /** 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 */ 1670 ElementNode *Document::createRootElement(const char *pcszRootElementName, 1633 1671 const char *pcszComment /* = NULL */) 1634 1672 { … … 1637 1675 1638 1676 // 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) 1643 1680 throw std::bad_alloc(); 1644 1681 xmlDocSetRootElement(m->plibDocument, plibRootNode); 1682 1645 1683 // now wrap this in C++ 1646 m->pRootElement = new ElementNode(NULL, NULL, plibRootNode);1684 m->pRootElement = new ElementNode(NULL, NULL, NULL, plibRootNode); 1647 1685 1648 1686 // add document global comment if specified 1649 1687 if (pcszComment != NULL) 1650 1688 { 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) 1654 1691 throw std::bad_alloc(); 1655 1692 xmlAddPrevSibling(plibRootNode, pComment); 1693 1656 1694 // now wrap this in C++ 1657 m->pComment = new ElementNode(NULL, NULL, pComment);1695 m->pComment = new ElementNode(NULL, NULL, NULL, pComment); 1658 1696 } 1659 1697
Note:
See TracChangeset
for help on using the changeset viewer.