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 |
- |