1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDOM.h" 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////// 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkXMLParser.h" 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkXMLParser::parse(const SkDOM& dom, const SkDOMNode* node) 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* elemName = dom.getName(node); 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->startElement(elemName)) 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 22d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDOM::AttrIter iter(dom, node); 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* name, *value; 25d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while ((name = iter.next(&value)) != NULL) 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (this->addAttribute(name, value)) 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((node = dom.getFirstChild(node)) != NULL) 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!this->parse(dom, node)) 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while ((node = dom.getNextSibling(node)) != NULL); 35d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return !this->endElement(elemName); 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////// 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct SkDOMAttr { 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* fName; 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* fValue; 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct SkDOMNode { 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* fName; 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDOMNode* fFirstChild; 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDOMNode* fNextSibling; 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t fAttrCount; 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t fType; 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t fPad; 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkDOMAttr* attrs() const 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (const SkDOMAttr*)(this + 1); 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDOMAttr* attrs() 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (SkDOMAttr*)(this + 1); 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////// 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define kMinChunkSize 512 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDOM::SkDOM() : fAlloc(kMinChunkSize), fRoot(NULL) 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDOM::~SkDOM() 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkDOM::Node* SkDOM::getRootNode() const 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fRoot; 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkDOM::Node* SkDOM::getFirstChild(const Node* node, const char name[]) const 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(node); 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const Node* child = node->fFirstChild; 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (name) 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (; child != NULL; child = child->fNextSibling) 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!strcmp(name, child->fName)) 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return child; 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkDOM::Node* SkDOM::getNextSibling(const Node* node, const char name[]) const 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(node); 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const Node* sibling = node->fNextSibling; 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (name) 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (; sibling != NULL; sibling = sibling->fNextSibling) 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!strcmp(name, sibling->fName)) 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return sibling; 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDOM::Type SkDOM::getType(const Node* node) const 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(node); 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (Type)node->fType; 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst char* SkDOM::getName(const Node* node) const 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(node); 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return node->fName; 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst char* SkDOM::findAttr(const Node* node, const char name[]) const 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(node); 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const Attr* attr = node->attrs(); 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const Attr* stop = attr + node->fAttrCount; 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (attr < stop) 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!strcmp(attr->fName, name)) 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return attr->fValue; 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com attr += 1; 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////////// 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkDOM::Attr* SkDOM::getFirstAttr(const Node* node) const 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return node->fAttrCount ? node->attrs() : NULL; 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkDOM::Attr* SkDOM::getNextAttr(const Node* node, const Attr* attr) const 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(node); 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (attr == NULL) 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (attr - node->attrs() + 1) < node->fAttrCount ? attr + 1 : NULL; 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst char* SkDOM::getAttrName(const Node* node, const Attr* attr) const 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(node); 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(attr); 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return attr->fName; 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst char* SkDOM::getAttrValue(const Node* node, const Attr* attr) const 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(node); 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(attr); 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return attr->fValue; 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////////////////////////////////////////////////////////////////// 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDOM::AttrIter::AttrIter(const SkDOM&, const SkDOM::Node* node) 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(node); 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAttr = node->attrs(); 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fStop = fAttr + node->fAttrCount; 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst char* SkDOM::AttrIter::next(const char** value) 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* name = NULL; 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fAttr < fStop) 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com name = fAttr->fName; 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value) 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *value = fAttr->fValue; 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAttr += 1; 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return name; 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkXMLParser.h" 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTDArray.h" 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic char* dupstr(SkChunkAlloc* chunk, const char src[]) 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(chunk && src); 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t len = strlen(src); 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com char* dst = (char*)chunk->alloc(len + 1, SkChunkAlloc::kThrow_AllocFailType); 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memcpy(dst, src, len + 1); 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return dst; 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkDOMParser : public SkXMLParser { 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool fNeedToFlush; 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDOMParser(SkChunkAlloc* chunk) : SkXMLParser(&fParserError), fAlloc(chunk) 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRoot = NULL; 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fLevel = 0; 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fNeedToFlush = true; 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDOM::Node* getRoot() const { return fRoot; } 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkXMLParserError fParserError; 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected: 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void flushAttributes() 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int attrCount = fAttrs.count(); 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDOM::Node* node = (SkDOM::Node*)fAlloc->alloc(sizeof(SkDOM::Node) + attrCount * sizeof(SkDOM::Attr), 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkChunkAlloc::kThrow_AllocFailType); 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com node->fName = fElemName; 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com node->fFirstChild = NULL; 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com node->fAttrCount = SkToU16(attrCount); 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com node->fType = SkDOM::kElement_Type; 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fRoot == NULL) 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com node->fNextSibling = NULL; 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRoot = node; 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else // this adds siblings in reverse order. gets corrected in onEndElement() 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDOM::Node* parent = fParentStack.top(); 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fRoot && parent); 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com node->fNextSibling = parent->fFirstChild; 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com parent->fFirstChild = node; 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fParentStack.push() = node; 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memcpy(node->attrs(), fAttrs.begin(), attrCount * sizeof(SkDOM::Attr)); 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAttrs.reset(); 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual bool onStartElement(const char elem[]) 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fLevel > 0 && fNeedToFlush) 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->flushAttributes(); 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fNeedToFlush = true; 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fElemName = dupstr(fAlloc, elem); 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ++fLevel; 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual bool onAddAttribute(const char name[], const char value[]) 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDOM::Attr* attr = fAttrs.append(); 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com attr->fName = dupstr(fAlloc, name); 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com attr->fValue = dupstr(fAlloc, value); 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual bool onEndElement(const char elem[]) 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com --fLevel; 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fNeedToFlush) 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->flushAttributes(); 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fNeedToFlush = false; 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDOM::Node* parent; 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fParentStack.pop(&parent); 2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDOM::Node* child = parent->fFirstChild; 2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDOM::Node* prev = NULL; 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (child) 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDOM::Node* next = child->fNextSibling; 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com child->fNextSibling = prev; 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prev = child; 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com child = next; 2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com parent->fFirstChild = prev; 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTDArray<SkDOM::Node*> fParentStack; 2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkChunkAlloc* fAlloc; 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDOM::Node* fRoot; 2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // state needed for flushAttributes() 2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTDArray<SkDOM::Attr> fAttrs; 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com char* fElemName; 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int fLevel; 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkDOM::Node* SkDOM::build(const char doc[], size_t len) 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAlloc.reset(); 2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDOMParser parser(&fAlloc); 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!parser.parse(doc, len)) 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(SkDebugf("xml parse error, line %d\n", parser.fParserError.getLineNumber());) 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRoot = NULL; 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAlloc.reset(); 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRoot = parser.getRoot(); 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fRoot; 3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////// 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void walk_dom(const SkDOM& dom, const SkDOM::Node* node, SkXMLParser* parser) 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* elem = dom.getName(node); 3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com parser->startElement(elem); 315d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDOM::AttrIter iter(dom, node); 3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* name; 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* value; 3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while ((name = iter.next(&value)) != NULL) 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com parser->addAttribute(name, value); 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com node = dom.getFirstChild(node, NULL); 3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (node) 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com walk_dom(dom, node, parser); 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com node = dom.getNextSibling(node, NULL); 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com parser->endElement(elem); 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkDOM::Node* SkDOM::copy(const SkDOM& dom, const SkDOM::Node* node) 3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAlloc.reset(); 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDOMParser parser(&fAlloc); 3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com walk_dom(dom, node, &parser); 3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRoot = parser.getRoot(); 3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fRoot; 3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////// 3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkDOM::countChildren(const Node* node, const char elem[]) const 3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = 0; 3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com node = this->getFirstChild(node, elem); 3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (node) 3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count += 1; 3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com node = this->getNextSibling(node, elem); 3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////// 3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkParse.h" 3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDOM::findS32(const Node* node, const char name[], int32_t* value) const 3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* vstr = this->findAttr(node, name); 3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return vstr && SkParse::FindS32(vstr, value); 3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDOM::findScalars(const Node* node, const char name[], SkScalar value[], int count) const 3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* vstr = this->findAttr(node, name); 3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return vstr && SkParse::FindScalars(vstr, value, count); 3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDOM::findHex(const Node* node, const char name[], uint32_t* value) const 3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* vstr = this->findAttr(node, name); 3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return vstr && SkParse::FindHex(vstr, value); 3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDOM::findBool(const Node* node, const char name[], bool* value) const 3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* vstr = this->findAttr(node, name); 3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return vstr && SkParse::FindBool(vstr, value); 3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkDOM::findList(const Node* node, const char name[], const char list[]) const 3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* vstr = this->findAttr(node, name); 3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return vstr ? SkParse::FindList(vstr, list) : -1; 3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDOM::hasAttr(const Node* node, const char name[], const char value[]) const 3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* vstr = this->findAttr(node, name); 3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return vstr && !strcmp(vstr, value); 3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDOM::hasS32(const Node* node, const char name[], int32_t target) const 3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* vstr = this->findAttr(node, name); 4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int32_t value; 4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return vstr && SkParse::FindS32(vstr, &value) && value == target; 4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDOM::hasScalar(const Node* node, const char name[], SkScalar target) const 4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* vstr = this->findAttr(node, name); 4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar value; 4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return vstr && SkParse::FindScalar(vstr, &value) && value == target; 4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDOM::hasHex(const Node* node, const char name[], uint32_t target) const 4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* vstr = this->findAttr(node, name); 4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t value; 4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return vstr && SkParse::FindHex(vstr, &value) && value == target; 4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDOM::hasBool(const Node* node, const char name[], bool target) const 4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* vstr = this->findAttr(node, name); 4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool value; 4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return vstr && SkParse::FindBool(vstr, &value) && value == target; 4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////// 4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void tab(int level) 4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (--level >= 0) 4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("\t"); 4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDOM::dump(const Node* node, int level) const 4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (node == NULL) 4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com node = this->getRootNode(); 4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (node) 4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tab(level); 4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("<%s", this->getName(node)); 4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const Attr* attr = node->attrs(); 4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const Attr* stop = attr + node->fAttrCount; 4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (; attr < stop; attr++) 4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf(" %s=\"%s\"", attr->fName, attr->fValue); 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const Node* child = this->getFirstChild(node); 4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (child) 4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf(">\n"); 4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (child) 4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->dump(child, level+1); 4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com child = this->getNextSibling(child); 4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tab(level); 4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("</%s>\n", node->fName); 4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else 4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("/>\n"); 4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDOM::UnitTest() 4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_SUPPORT_UNITTEST 470d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com static const char gDoc[] = 4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "<root a='1' b='2'>" 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "<elem1 c='3' />" 4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "<elem2 d='4' />" 4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "<elem3 e='5'>" 4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "<subelem1/>" 4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "<subelem2 f='6' g='7'/>" 4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "</elem3>" 4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "<elem4 h='8'/>" 4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com "</root>" 4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ; 4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDOM dom; 4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(dom.getRootNode() == NULL); 4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const Node* root = dom.build(gDoc, sizeof(gDoc) - 1); 4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(root && dom.getRootNode() == root); 4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* v = dom.findAttr(root, "a"); 4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(v && !strcmp(v, "1")); 4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com v = dom.findAttr(root, "b"); 4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(v && !strcmp(v, "2")); 4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com v = dom.findAttr(root, "c"); 4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(v == NULL); 4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(dom.getFirstChild(root, "elem1")); 4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(!dom.getFirstChild(root, "subelem1")); 4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dom.dump(); 5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 504