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