| Index: skia/xml/SkDOM.cpp
|
| ===================================================================
|
| --- skia/xml/SkDOM.cpp (revision 16859)
|
| +++ skia/xml/SkDOM.cpp (working copy)
|
| @@ -1,512 +0,0 @@
|
| -/* libs/graphics/xml/SkDOM.cpp
|
| -**
|
| -** Copyright 2006, The Android Open Source Project
|
| -**
|
| -** Licensed under the Apache License, Version 2.0 (the "License");
|
| -** you may not use this file except in compliance with the License.
|
| -** You may obtain a copy of the License at
|
| -**
|
| -** http://www.apache.org/licenses/LICENSE-2.0
|
| -**
|
| -** Unless required by applicable law or agreed to in writing, software
|
| -** distributed under the License is distributed on an "AS IS" BASIS,
|
| -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| -** See the License for the specific language governing permissions and
|
| -** limitations under the License.
|
| -*/
|
| -
|
| -#include "SkDOM.h"
|
| -
|
| -/////////////////////////////////////////////////////////////////////////
|
| -
|
| -#include "SkXMLParser.h"
|
| -
|
| -bool SkXMLParser::parse(const SkDOM& dom, const SkDOMNode* node)
|
| -{
|
| - const char* elemName = dom.getName(node);
|
| -
|
| - if (this->startElement(elemName))
|
| - return false;
|
| -
|
| - SkDOM::AttrIter iter(dom, node);
|
| - const char* name, *value;
|
| -
|
| - while ((name = iter.next(&value)) != NULL)
|
| - if (this->addAttribute(name, value))
|
| - return false;
|
| -
|
| - if ((node = dom.getFirstChild(node)) != NULL)
|
| - do {
|
| - if (!this->parse(dom, node))
|
| - return false;
|
| - } while ((node = dom.getNextSibling(node)) != NULL);
|
| -
|
| - return !this->endElement(elemName);
|
| -}
|
| -
|
| -/////////////////////////////////////////////////////////////////////////
|
| -
|
| -struct SkDOMAttr {
|
| - const char* fName;
|
| - const char* fValue;
|
| -};
|
| -
|
| -struct SkDOMNode {
|
| - const char* fName;
|
| - SkDOMNode* fFirstChild;
|
| - SkDOMNode* fNextSibling;
|
| - uint16_t fAttrCount;
|
| - uint8_t fType;
|
| - uint8_t fPad;
|
| -
|
| - const SkDOMAttr* attrs() const
|
| - {
|
| - return (const SkDOMAttr*)(this + 1);
|
| - }
|
| - SkDOMAttr* attrs()
|
| - {
|
| - return (SkDOMAttr*)(this + 1);
|
| - }
|
| -};
|
| -
|
| -/////////////////////////////////////////////////////////////////////////
|
| -
|
| -#define kMinChunkSize 512
|
| -
|
| -SkDOM::SkDOM() : fAlloc(kMinChunkSize), fRoot(NULL)
|
| -{
|
| -}
|
| -
|
| -SkDOM::~SkDOM()
|
| -{
|
| -}
|
| -
|
| -const SkDOM::Node* SkDOM::getRootNode() const
|
| -{
|
| - return fRoot;
|
| -}
|
| -
|
| -const SkDOM::Node* SkDOM::getFirstChild(const Node* node, const char name[]) const
|
| -{
|
| - SkASSERT(node);
|
| - const Node* child = node->fFirstChild;
|
| -
|
| - if (name)
|
| - {
|
| - for (; child != NULL; child = child->fNextSibling)
|
| - if (!strcmp(name, child->fName))
|
| - break;
|
| - }
|
| - return child;
|
| -}
|
| -
|
| -const SkDOM::Node* SkDOM::getNextSibling(const Node* node, const char name[]) const
|
| -{
|
| - SkASSERT(node);
|
| - const Node* sibling = node->fNextSibling;
|
| - if (name)
|
| - {
|
| - for (; sibling != NULL; sibling = sibling->fNextSibling)
|
| - if (!strcmp(name, sibling->fName))
|
| - break;
|
| - }
|
| - return sibling;
|
| -}
|
| -
|
| -SkDOM::Type SkDOM::getType(const Node* node) const
|
| -{
|
| - SkASSERT(node);
|
| - return (Type)node->fType;
|
| -}
|
| -
|
| -const char* SkDOM::getName(const Node* node) const
|
| -{
|
| - SkASSERT(node);
|
| - return node->fName;
|
| -}
|
| -
|
| -const char* SkDOM::findAttr(const Node* node, const char name[]) const
|
| -{
|
| - SkASSERT(node);
|
| - const Attr* attr = node->attrs();
|
| - const Attr* stop = attr + node->fAttrCount;
|
| -
|
| - while (attr < stop)
|
| - {
|
| - if (!strcmp(attr->fName, name))
|
| - return attr->fValue;
|
| - attr += 1;
|
| - }
|
| - return NULL;
|
| -}
|
| -
|
| -/////////////////////////////////////////////////////////////////////////////////////
|
| -
|
| -const SkDOM::Attr* SkDOM::getFirstAttr(const Node* node) const
|
| -{
|
| - return node->fAttrCount ? node->attrs() : NULL;
|
| -}
|
| -
|
| -const SkDOM::Attr* SkDOM::getNextAttr(const Node* node, const Attr* attr) const
|
| -{
|
| - SkASSERT(node);
|
| - if (attr == NULL)
|
| - return NULL;
|
| - return (attr - node->attrs() + 1) < node->fAttrCount ? attr + 1 : NULL;
|
| -}
|
| -
|
| -const char* SkDOM::getAttrName(const Node* node, const Attr* attr) const
|
| -{
|
| - SkASSERT(node);
|
| - SkASSERT(attr);
|
| - return attr->fName;
|
| -}
|
| -
|
| -const char* SkDOM::getAttrValue(const Node* node, const Attr* attr) const
|
| -{
|
| - SkASSERT(node);
|
| - SkASSERT(attr);
|
| - return attr->fValue;
|
| -}
|
| -
|
| -/////////////////////////////////////////////////////////////////////////////////////
|
| -
|
| -SkDOM::AttrIter::AttrIter(const SkDOM&, const SkDOM::Node* node)
|
| -{
|
| - SkASSERT(node);
|
| - fAttr = node->attrs();
|
| - fStop = fAttr + node->fAttrCount;
|
| -}
|
| -
|
| -const char* SkDOM::AttrIter::next(const char** value)
|
| -{
|
| - const char* name = NULL;
|
| -
|
| - if (fAttr < fStop)
|
| - {
|
| - name = fAttr->fName;
|
| - if (value)
|
| - *value = fAttr->fValue;
|
| - fAttr += 1;
|
| - }
|
| - return name;
|
| -}
|
| -
|
| -//////////////////////////////////////////////////////////////////////////////
|
| -
|
| -#include "SkXMLParser.h"
|
| -#include "SkTDArray.h"
|
| -
|
| -static char* dupstr(SkChunkAlloc* chunk, const char src[])
|
| -{
|
| - SkASSERT(chunk && src);
|
| - size_t len = strlen(src);
|
| - char* dst = (char*)chunk->alloc(len + 1, SkChunkAlloc::kThrow_AllocFailType);
|
| - memcpy(dst, src, len + 1);
|
| - return dst;
|
| -}
|
| -
|
| -class SkDOMParser : public SkXMLParser {
|
| - bool fNeedToFlush;
|
| -public:
|
| - SkDOMParser(SkChunkAlloc* chunk) : SkXMLParser(&fParserError), fAlloc(chunk)
|
| - {
|
| - fRoot = NULL;
|
| - fLevel = 0;
|
| - fNeedToFlush = true;
|
| - }
|
| - SkDOM::Node* getRoot() const { return fRoot; }
|
| - SkXMLParserError fParserError;
|
| -protected:
|
| - void flushAttributes()
|
| - {
|
| - int attrCount = fAttrs.count();
|
| -
|
| - SkDOM::Node* node = (SkDOM::Node*)fAlloc->alloc(sizeof(SkDOM::Node) + attrCount * sizeof(SkDOM::Attr),
|
| - SkChunkAlloc::kThrow_AllocFailType);
|
| -
|
| - node->fName = fElemName;
|
| - node->fFirstChild = NULL;
|
| - node->fAttrCount = SkToU16(attrCount);
|
| - node->fType = SkDOM::kElement_Type;
|
| -
|
| - if (fRoot == NULL)
|
| - {
|
| - node->fNextSibling = NULL;
|
| - fRoot = node;
|
| - }
|
| - else // this adds siblings in reverse order. gets corrected in onEndElement()
|
| - {
|
| - SkDOM::Node* parent = fParentStack.top();
|
| - SkASSERT(fRoot && parent);
|
| - node->fNextSibling = parent->fFirstChild;
|
| - parent->fFirstChild = node;
|
| - }
|
| - *fParentStack.push() = node;
|
| -
|
| - memcpy(node->attrs(), fAttrs.begin(), attrCount * sizeof(SkDOM::Attr));
|
| - fAttrs.reset();
|
| -
|
| - }
|
| - virtual bool onStartElement(const char elem[])
|
| - {
|
| - if (fLevel > 0 && fNeedToFlush)
|
| - this->flushAttributes();
|
| - fNeedToFlush = true;
|
| - fElemName = dupstr(fAlloc, elem);
|
| - ++fLevel;
|
| - return false;
|
| - }
|
| - virtual bool onAddAttribute(const char name[], const char value[])
|
| - {
|
| - SkDOM::Attr* attr = fAttrs.append();
|
| - attr->fName = dupstr(fAlloc, name);
|
| - attr->fValue = dupstr(fAlloc, value);
|
| - return false;
|
| - }
|
| - virtual bool onEndElement(const char elem[])
|
| - {
|
| - --fLevel;
|
| - if (fNeedToFlush)
|
| - this->flushAttributes();
|
| - fNeedToFlush = false;
|
| -
|
| - SkDOM::Node* parent;
|
| -
|
| - fParentStack.pop(&parent);
|
| -
|
| - SkDOM::Node* child = parent->fFirstChild;
|
| - SkDOM::Node* prev = NULL;
|
| - while (child)
|
| - {
|
| - SkDOM::Node* next = child->fNextSibling;
|
| - child->fNextSibling = prev;
|
| - prev = child;
|
| - child = next;
|
| - }
|
| - parent->fFirstChild = prev;
|
| - return false;
|
| - }
|
| -private:
|
| - SkTDArray<SkDOM::Node*> fParentStack;
|
| - SkChunkAlloc* fAlloc;
|
| - SkDOM::Node* fRoot;
|
| -
|
| - // state needed for flushAttributes()
|
| - SkTDArray<SkDOM::Attr> fAttrs;
|
| - char* fElemName;
|
| - int fLevel;
|
| -};
|
| -
|
| -const SkDOM::Node* SkDOM::build(const char doc[], size_t len)
|
| -{
|
| - fAlloc.reset();
|
| - SkDOMParser parser(&fAlloc);
|
| - if (!parser.parse(doc, len))
|
| - {
|
| - SkDEBUGCODE(SkDebugf("xml parse error, line %d\n", parser.fParserError.getLineNumber());)
|
| - fRoot = NULL;
|
| - fAlloc.reset();
|
| - return NULL;
|
| - }
|
| - fRoot = parser.getRoot();
|
| - return fRoot;
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////
|
| -
|
| -static void walk_dom(const SkDOM& dom, const SkDOM::Node* node, SkXMLParser* parser)
|
| -{
|
| - const char* elem = dom.getName(node);
|
| -
|
| - parser->startElement(elem);
|
| -
|
| - SkDOM::AttrIter iter(dom, node);
|
| - const char* name;
|
| - const char* value;
|
| - while ((name = iter.next(&value)) != NULL)
|
| - parser->addAttribute(name, value);
|
| -
|
| - node = dom.getFirstChild(node, NULL);
|
| - while (node)
|
| - {
|
| - walk_dom(dom, node, parser);
|
| - node = dom.getNextSibling(node, NULL);
|
| - }
|
| -
|
| - parser->endElement(elem);
|
| -}
|
| -
|
| -const SkDOM::Node* SkDOM::copy(const SkDOM& dom, const SkDOM::Node* node)
|
| -{
|
| - fAlloc.reset();
|
| - SkDOMParser parser(&fAlloc);
|
| -
|
| - walk_dom(dom, node, &parser);
|
| -
|
| - fRoot = parser.getRoot();
|
| - return fRoot;
|
| -}
|
| -
|
| -//////////////////////////////////////////////////////////////////////////
|
| -
|
| -int SkDOM::countChildren(const Node* node, const char elem[]) const
|
| -{
|
| - int count = 0;
|
| -
|
| - node = this->getFirstChild(node, elem);
|
| - while (node)
|
| - {
|
| - count += 1;
|
| - node = this->getNextSibling(node, elem);
|
| - }
|
| - return count;
|
| -}
|
| -
|
| -//////////////////////////////////////////////////////////////////////////
|
| -
|
| -#include "SkParse.h"
|
| -
|
| -bool SkDOM::findS32(const Node* node, const char name[], int32_t* value) const
|
| -{
|
| - const char* vstr = this->findAttr(node, name);
|
| - return vstr && SkParse::FindS32(vstr, value);
|
| -}
|
| -
|
| -bool SkDOM::findScalars(const Node* node, const char name[], SkScalar value[], int count) const
|
| -{
|
| - const char* vstr = this->findAttr(node, name);
|
| - return vstr && SkParse::FindScalars(vstr, value, count);
|
| -}
|
| -
|
| -bool SkDOM::findHex(const Node* node, const char name[], uint32_t* value) const
|
| -{
|
| - const char* vstr = this->findAttr(node, name);
|
| - return vstr && SkParse::FindHex(vstr, value);
|
| -}
|
| -
|
| -bool SkDOM::findBool(const Node* node, const char name[], bool* value) const
|
| -{
|
| - const char* vstr = this->findAttr(node, name);
|
| - return vstr && SkParse::FindBool(vstr, value);
|
| -}
|
| -
|
| -int SkDOM::findList(const Node* node, const char name[], const char list[]) const
|
| -{
|
| - const char* vstr = this->findAttr(node, name);
|
| - return vstr ? SkParse::FindList(vstr, list) : -1;
|
| -}
|
| -
|
| -bool SkDOM::hasAttr(const Node* node, const char name[], const char value[]) const
|
| -{
|
| - const char* vstr = this->findAttr(node, name);
|
| - return vstr && !strcmp(vstr, value);
|
| -}
|
| -
|
| -bool SkDOM::hasS32(const Node* node, const char name[], int32_t target) const
|
| -{
|
| - const char* vstr = this->findAttr(node, name);
|
| - int32_t value;
|
| - return vstr && SkParse::FindS32(vstr, &value) && value == target;
|
| -}
|
| -
|
| -bool SkDOM::hasScalar(const Node* node, const char name[], SkScalar target) const
|
| -{
|
| - const char* vstr = this->findAttr(node, name);
|
| - SkScalar value;
|
| - return vstr && SkParse::FindScalar(vstr, &value) && value == target;
|
| -}
|
| -
|
| -bool SkDOM::hasHex(const Node* node, const char name[], uint32_t target) const
|
| -{
|
| - const char* vstr = this->findAttr(node, name);
|
| - uint32_t value;
|
| - return vstr && SkParse::FindHex(vstr, &value) && value == target;
|
| -}
|
| -
|
| -bool SkDOM::hasBool(const Node* node, const char name[], bool target) const
|
| -{
|
| - const char* vstr = this->findAttr(node, name);
|
| - bool value;
|
| - return vstr && SkParse::FindBool(vstr, &value) && value == target;
|
| -}
|
| -
|
| -//////////////////////////////////////////////////////////////////////////
|
| -
|
| -#ifdef SK_DEBUG
|
| -
|
| -static void tab(int level)
|
| -{
|
| - while (--level >= 0)
|
| - SkDebugf("\t");
|
| -}
|
| -
|
| -void SkDOM::dump(const Node* node, int level) const
|
| -{
|
| - if (node == NULL)
|
| - node = this->getRootNode();
|
| - if (node)
|
| - {
|
| - tab(level);
|
| - SkDebugf("<%s", this->getName(node));
|
| -
|
| - const Attr* attr = node->attrs();
|
| - const Attr* stop = attr + node->fAttrCount;
|
| - for (; attr < stop; attr++)
|
| - SkDebugf(" %s=\"%s\"", attr->fName, attr->fValue);
|
| -
|
| - const Node* child = this->getFirstChild(node);
|
| - if (child)
|
| - {
|
| - SkDebugf(">\n");
|
| - while (child)
|
| - {
|
| - this->dump(child, level+1);
|
| - child = this->getNextSibling(child);
|
| - }
|
| - tab(level);
|
| - SkDebugf("</%s>\n", node->fName);
|
| - }
|
| - else
|
| - SkDebugf("/>\n");
|
| - }
|
| -}
|
| -
|
| -void SkDOM::UnitTest()
|
| -{
|
| -#ifdef SK_SUPPORT_UNITTEST
|
| - static const char gDoc[] =
|
| - "<root a='1' b='2'>"
|
| - "<elem1 c='3' />"
|
| - "<elem2 d='4' />"
|
| - "<elem3 e='5'>"
|
| - "<subelem1/>"
|
| - "<subelem2 f='6' g='7'/>"
|
| - "</elem3>"
|
| - "<elem4 h='8'/>"
|
| - "</root>"
|
| - ;
|
| -
|
| - SkDOM dom;
|
| -
|
| - SkASSERT(dom.getRootNode() == NULL);
|
| -
|
| - const Node* root = dom.build(gDoc, sizeof(gDoc) - 1);
|
| - SkASSERT(root && dom.getRootNode() == root);
|
| -
|
| - const char* v = dom.findAttr(root, "a");
|
| - SkASSERT(v && !strcmp(v, "1"));
|
| - v = dom.findAttr(root, "b");
|
| - SkASSERT(v && !strcmp(v, "2"));
|
| - v = dom.findAttr(root, "c");
|
| - SkASSERT(v == NULL);
|
| -
|
| - SkASSERT(dom.getFirstChild(root, "elem1"));
|
| - SkASSERT(!dom.getFirstChild(root, "subelem1"));
|
| -
|
| - dom.dump();
|
| -#endif
|
| -}
|
| -
|
| -#endif
|
| -
|
|
|