1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 2685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com/* 3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2006 The Android Open Source Project 4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * 5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file. 7685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com */ 8685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 9bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkDOM.h" 11bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 12bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////// 13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 14bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkXMLParser.h" 15bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 16bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkXMLParser::parse(const SkDOM& dom, const SkDOMNode* node) 17bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 18bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* elemName = dom.getName(node); 19bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 20bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (this->startElement(elemName)) 21bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; 22dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com 23bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDOM::AttrIter iter(dom, node); 24bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* name, *value; 25dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com 26bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while ((name = iter.next(&value)) != NULL) 27bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (this->addAttribute(name, value)) 28bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; 29bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 30bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if ((node = dom.getFirstChild(node)) != NULL) 31bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com do { 32bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (!this->parse(dom, node)) 33bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; 34bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } while ((node = dom.getNextSibling(node)) != NULL); 35dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com 36bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return !this->endElement(elemName); 37bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 38bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 39bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////// 40bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 41bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstruct SkDOMAttr { 42bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* fName; 43bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* fValue; 44bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}; 45bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 46bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstruct SkDOMNode { 47bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* fName; 48bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDOMNode* fFirstChild; 49bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDOMNode* fNextSibling; 50bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint16_t fAttrCount; 51bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint8_t fType; 52bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint8_t fPad; 53bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 54bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkDOMAttr* attrs() const 55bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 56bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return (const SkDOMAttr*)(this + 1); 57bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 58bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDOMAttr* attrs() 59bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 60bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return (SkDOMAttr*)(this + 1); 61bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 62bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}; 63bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 64bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////// 65bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 66bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define kMinChunkSize 512 67bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 68bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkDOM::SkDOM() : fAlloc(kMinChunkSize), fRoot(NULL) 69bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 70bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 71bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 72bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkDOM::~SkDOM() 73bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 74bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 75bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 76bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst SkDOM::Node* SkDOM::getRootNode() const 77bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 78bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return fRoot; 79bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 80bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 81bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst SkDOM::Node* SkDOM::getFirstChild(const Node* node, const char name[]) const 82bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 83bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(node); 84bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const Node* child = node->fFirstChild; 85bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 86bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (name) 87bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 88bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com for (; child != NULL; child = child->fNextSibling) 89bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (!strcmp(name, child->fName)) 90bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 91bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 92bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return child; 93bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 94bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 95bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst SkDOM::Node* SkDOM::getNextSibling(const Node* node, const char name[]) const 96bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 97bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(node); 98bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const Node* sibling = node->fNextSibling; 99bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (name) 100bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 101bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com for (; sibling != NULL; sibling = sibling->fNextSibling) 102bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (!strcmp(name, sibling->fName)) 103bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 104bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 105bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return sibling; 106bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 107bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 108bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkDOM::Type SkDOM::getType(const Node* node) const 109bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 110bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(node); 111bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return (Type)node->fType; 112bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 113bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 114bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst char* SkDOM::getName(const Node* node) const 115bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 116bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(node); 117bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return node->fName; 118bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 119bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 120bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst char* SkDOM::findAttr(const Node* node, const char name[]) const 121bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 122bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(node); 123bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const Attr* attr = node->attrs(); 124bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const Attr* stop = attr + node->fAttrCount; 125bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 126bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (attr < stop) 127bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (!strcmp(attr->fName, name)) 129bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return attr->fValue; 130bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com attr += 1; 131bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 132bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return NULL; 133bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 135bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////////////////// 136bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 137bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst SkDOM::Attr* SkDOM::getFirstAttr(const Node* node) const 138bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 139bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return node->fAttrCount ? node->attrs() : NULL; 140bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 141bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 142bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst SkDOM::Attr* SkDOM::getNextAttr(const Node* node, const Attr* attr) const 143bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 144bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(node); 145bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (attr == NULL) 146bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return NULL; 147bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return (attr - node->attrs() + 1) < node->fAttrCount ? attr + 1 : NULL; 148bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 149bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 150bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst char* SkDOM::getAttrName(const Node* node, const Attr* attr) const 151bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 152bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(node); 153bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(attr); 154bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return attr->fName; 155bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 156bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 157bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst char* SkDOM::getAttrValue(const Node* node, const Attr* attr) const 158bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 159bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(node); 160bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(attr); 161bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return attr->fValue; 162bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 163bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 164bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com///////////////////////////////////////////////////////////////////////////////////// 165bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 166bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkDOM::AttrIter::AttrIter(const SkDOM&, const SkDOM::Node* node) 167bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 168bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(node); 169bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fAttr = node->attrs(); 170bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fStop = fAttr + node->fAttrCount; 171bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 172bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 173bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst char* SkDOM::AttrIter::next(const char** value) 174bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 175bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* name = NULL; 176bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 177bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (fAttr < fStop) 178bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 179bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com name = fAttr->fName; 180bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (value) 181bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *value = fAttr->fValue; 182bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fAttr += 1; 183bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 184bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return name; 185bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 186bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 187bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com////////////////////////////////////////////////////////////////////////////// 188bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 189bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkXMLParser.h" 190bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkTDArray.h" 191bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 192bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic char* dupstr(SkChunkAlloc* chunk, const char src[]) 193bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 194bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(chunk && src); 195bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com size_t len = strlen(src); 196bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com char* dst = (char*)chunk->alloc(len + 1, SkChunkAlloc::kThrow_AllocFailType); 197bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com memcpy(dst, src, len + 1); 198bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return dst; 199bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 200bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 201bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comclass SkDOMParser : public SkXMLParser { 202bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bool fNeedToFlush; 203bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.compublic: 204bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDOMParser(SkChunkAlloc* chunk) : SkXMLParser(&fParserError), fAlloc(chunk) 205bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 206bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRoot = NULL; 207bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fLevel = 0; 208bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fNeedToFlush = true; 209bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 210bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDOM::Node* getRoot() const { return fRoot; } 211bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkXMLParserError fParserError; 212bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comprotected: 213bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void flushAttributes() 214bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 215bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int attrCount = fAttrs.count(); 216bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 217bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDOM::Node* node = (SkDOM::Node*)fAlloc->alloc(sizeof(SkDOM::Node) + attrCount * sizeof(SkDOM::Attr), 218bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkChunkAlloc::kThrow_AllocFailType); 219bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 220bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com node->fName = fElemName; 221bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com node->fFirstChild = NULL; 222bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com node->fAttrCount = SkToU16(attrCount); 223bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com node->fType = SkDOM::kElement_Type; 224bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 225bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (fRoot == NULL) 226bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 227bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com node->fNextSibling = NULL; 228bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRoot = node; 229bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 230bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com else // this adds siblings in reverse order. gets corrected in onEndElement() 231bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 232bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDOM::Node* parent = fParentStack.top(); 233bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(fRoot && parent); 234bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com node->fNextSibling = parent->fFirstChild; 235bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com parent->fFirstChild = node; 236bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 237bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *fParentStack.push() = node; 238bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 239bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com memcpy(node->attrs(), fAttrs.begin(), attrCount * sizeof(SkDOM::Attr)); 240bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fAttrs.reset(); 241bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 242bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 243bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com virtual bool onStartElement(const char elem[]) 244bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 245bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (fLevel > 0 && fNeedToFlush) 246bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->flushAttributes(); 247bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fNeedToFlush = true; 248bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fElemName = dupstr(fAlloc, elem); 249bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com ++fLevel; 250bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; 251bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 252bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com virtual bool onAddAttribute(const char name[], const char value[]) 253bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 254bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDOM::Attr* attr = fAttrs.append(); 255bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com attr->fName = dupstr(fAlloc, name); 256bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com attr->fValue = dupstr(fAlloc, value); 257bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; 258bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 259bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com virtual bool onEndElement(const char elem[]) 260bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 261bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com --fLevel; 262bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (fNeedToFlush) 263bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->flushAttributes(); 264bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fNeedToFlush = false; 265bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 266bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDOM::Node* parent; 267bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 268bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fParentStack.pop(&parent); 269bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 270bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDOM::Node* child = parent->fFirstChild; 271bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDOM::Node* prev = NULL; 272bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (child) 273bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 274bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDOM::Node* next = child->fNextSibling; 275bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com child->fNextSibling = prev; 276bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com prev = child; 277bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com child = next; 278bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 279bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com parent->fFirstChild = prev; 280bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; 281bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 282bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comprivate: 283bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkTDArray<SkDOM::Node*> fParentStack; 284bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkChunkAlloc* fAlloc; 285bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDOM::Node* fRoot; 286bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 287bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // state needed for flushAttributes() 288bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkTDArray<SkDOM::Attr> fAttrs; 289bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com char* fElemName; 290bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int fLevel; 291bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}; 292bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 293bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst SkDOM::Node* SkDOM::build(const char doc[], size_t len) 294bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 295bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fAlloc.reset(); 296bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDOMParser parser(&fAlloc); 297bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (!parser.parse(doc, len)) 298bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 299bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDEBUGCODE(SkDebugf("xml parse error, line %d\n", parser.fParserError.getLineNumber());) 300bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRoot = NULL; 301bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fAlloc.reset(); 302bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return NULL; 303bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 304bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRoot = parser.getRoot(); 305bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return fRoot; 306bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 307bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 308bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////// 309bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 310bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic void walk_dom(const SkDOM& dom, const SkDOM::Node* node, SkXMLParser* parser) 311bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 312bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* elem = dom.getName(node); 313bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 314bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com parser->startElement(elem); 315dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com 316bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDOM::AttrIter iter(dom, node); 317bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* name; 318bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* value; 319bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while ((name = iter.next(&value)) != NULL) 320bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com parser->addAttribute(name, value); 321bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 322bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com node = dom.getFirstChild(node, NULL); 323bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (node) 324bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 325bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com walk_dom(dom, node, parser); 326bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com node = dom.getNextSibling(node, NULL); 327bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 328bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 329bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com parser->endElement(elem); 330bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 331bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 332bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst SkDOM::Node* SkDOM::copy(const SkDOM& dom, const SkDOM::Node* node) 333bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 334bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fAlloc.reset(); 335bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDOMParser parser(&fAlloc); 336bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 337bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com walk_dom(dom, node, &parser); 338bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 339bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRoot = parser.getRoot(); 340bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return fRoot; 341bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 342bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 343bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com////////////////////////////////////////////////////////////////////////// 344bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 345bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint SkDOM::countChildren(const Node* node, const char elem[]) const 346bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 347bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int count = 0; 348bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 349bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com node = this->getFirstChild(node, elem); 350bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (node) 351bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 352bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com count += 1; 353bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com node = this->getNextSibling(node, elem); 354bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 355bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return count; 356bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 357bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 358bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com////////////////////////////////////////////////////////////////////////// 359bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 360bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkParse.h" 361bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 362bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkDOM::findS32(const Node* node, const char name[], int32_t* value) const 363bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 364bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* vstr = this->findAttr(node, name); 365bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return vstr && SkParse::FindS32(vstr, value); 366bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 367bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 368bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkDOM::findScalars(const Node* node, const char name[], SkScalar value[], int count) const 369bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 370bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* vstr = this->findAttr(node, name); 371bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return vstr && SkParse::FindScalars(vstr, value, count); 372bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 373bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 374bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkDOM::findHex(const Node* node, const char name[], uint32_t* value) const 375bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 376bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* vstr = this->findAttr(node, name); 377bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return vstr && SkParse::FindHex(vstr, value); 378bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 379bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 380bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkDOM::findBool(const Node* node, const char name[], bool* value) const 381bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 382bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* vstr = this->findAttr(node, name); 383bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return vstr && SkParse::FindBool(vstr, value); 384bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 385bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 386bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comint SkDOM::findList(const Node* node, const char name[], const char list[]) const 387bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 388bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* vstr = this->findAttr(node, name); 389bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return vstr ? SkParse::FindList(vstr, list) : -1; 390bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 391bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 392bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkDOM::hasAttr(const Node* node, const char name[], const char value[]) const 393bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 394bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* vstr = this->findAttr(node, name); 395bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return vstr && !strcmp(vstr, value); 396bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 397bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 398bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkDOM::hasS32(const Node* node, const char name[], int32_t target) const 399bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 400bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* vstr = this->findAttr(node, name); 401bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int32_t value; 402bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return vstr && SkParse::FindS32(vstr, &value) && value == target; 403bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 404bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 405bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkDOM::hasScalar(const Node* node, const char name[], SkScalar target) const 406bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 407bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* vstr = this->findAttr(node, name); 408bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar value; 409bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return vstr && SkParse::FindScalar(vstr, &value) && value == target; 410bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 411bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 412bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkDOM::hasHex(const Node* node, const char name[], uint32_t target) const 413bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 414bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* vstr = this->findAttr(node, name); 415bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t value; 416bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return vstr && SkParse::FindHex(vstr, &value) && value == target; 417bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 418bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 419bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkDOM::hasBool(const Node* node, const char name[], bool target) const 420bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 421bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* vstr = this->findAttr(node, name); 422bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bool value; 423bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return vstr && SkParse::FindBool(vstr, &value) && value == target; 424bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 425bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 426bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com////////////////////////////////////////////////////////////////////////// 427bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 428bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG 429bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 430bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic void tab(int level) 431bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 432bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (--level >= 0) 433bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDebugf("\t"); 434bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 435bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 436bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkDOM::dump(const Node* node, int level) const 437bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 438bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (node == NULL) 439bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com node = this->getRootNode(); 440bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (node) 441bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 442bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tab(level); 443bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDebugf("<%s", this->getName(node)); 444bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 445bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const Attr* attr = node->attrs(); 446bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const Attr* stop = attr + node->fAttrCount; 447bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com for (; attr < stop; attr++) 448bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDebugf(" %s=\"%s\"", attr->fName, attr->fValue); 449bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 450bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const Node* child = this->getFirstChild(node); 451bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (child) 452bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 453bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDebugf(">\n"); 454bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (child) 455bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 456bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->dump(child, level+1); 457bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com child = this->getNextSibling(child); 458bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 459bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tab(level); 460bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDebugf("</%s>\n", node->fName); 461bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 462bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com else 463bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDebugf("/>\n"); 464bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 465bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 466bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 467bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkDOM::UnitTest() 468bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com{ 469bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_SUPPORT_UNITTEST 470dfb3e3c0faadabc131ac1532e29ca71667328513rmistry@google.com static const char gDoc[] = 471bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com "<root a='1' b='2'>" 472bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com "<elem1 c='3' />" 473bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com "<elem2 d='4' />" 474bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com "<elem3 e='5'>" 475bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com "<subelem1/>" 476bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com "<subelem2 f='6' g='7'/>" 477bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com "</elem3>" 478bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com "<elem4 h='8'/>" 479bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com "</root>" 480bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com ; 481bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 482bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDOM dom; 483bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 484bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(dom.getRootNode() == NULL); 485bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 486bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const Node* root = dom.build(gDoc, sizeof(gDoc) - 1); 487bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(root && dom.getRootNode() == root); 488bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 489bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const char* v = dom.findAttr(root, "a"); 490bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(v && !strcmp(v, "1")); 491bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com v = dom.findAttr(root, "b"); 492bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(v && !strcmp(v, "2")); 493bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com v = dom.findAttr(root, "c"); 494bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(v == NULL); 495bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 496bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(dom.getFirstChild(root, "elem1")); 497bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(!dom.getFirstChild(root, "subelem1")); 498bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 499bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dom.dump(); 500bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 501bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 502bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 503bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 504