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