Index: src/xml/SkDOM.cpp |
diff --git a/src/xml/SkDOM.cpp b/src/xml/SkDOM.cpp |
index 98546089fa287ccc389b327000fdd5323f74b829..eb1bc092fecb9e1f9f7a1397873d14da56ff0617 100644 |
--- a/src/xml/SkDOM.cpp |
+++ b/src/xml/SkDOM.cpp |
@@ -8,11 +8,12 @@ |
#include "SkDOM.h" |
+#include "SkStream.h" |
+#include "SkXMLWriter.h" |
///////////////////////////////////////////////////////////////////////// |
#include "SkXMLParser.h" |
- |
bool SkXMLParser::parse(const SkDOM& dom, const SkDOMNode* node) |
{ |
const char* elemName = dom.getName(node); |
@@ -199,19 +200,22 @@ static char* dupstr(SkChunkAlloc* chunk, const char src[]) |
} |
class SkDOMParser : public SkXMLParser { |
- bool fNeedToFlush; |
public: |
SkDOMParser(SkChunkAlloc* chunk) : SkXMLParser(&fParserError), fAlloc(chunk) |
{ |
+ fAlloc->reset(); |
fRoot = NULL; |
fLevel = 0; |
fNeedToFlush = true; |
} |
SkDOM::Node* getRoot() const { return fRoot; } |
SkXMLParserError fParserError; |
+ |
protected: |
void flushAttributes() |
{ |
+ SkASSERT(fLevel > 0); |
+ |
int attrCount = fAttrs.count(); |
SkDOM::Node* node = (SkDOM::Node*)fAlloc->alloc(sizeof(SkDOM::Node) + attrCount * sizeof(SkDOM::Attr), |
@@ -220,7 +224,7 @@ protected: |
node->fName = fElemName; |
node->fFirstChild = NULL; |
node->fAttrCount = SkToU16(attrCount); |
- node->fType = SkDOM::kElement_Type; |
+ node->fType = fElemType; |
if (fRoot == NULL) |
{ |
@@ -240,24 +244,20 @@ protected: |
fAttrs.reset(); |
} |
- virtual bool onStartElement(const char elem[]) |
- { |
- if (fLevel > 0 && fNeedToFlush) |
- this->flushAttributes(); |
- fNeedToFlush = true; |
- fElemName = dupstr(fAlloc, elem); |
- ++fLevel; |
+ |
+ bool onStartElement(const char elem[]) override { |
+ this->startCommon(elem, SkDOM::kElement_Type); |
return false; |
} |
- virtual bool onAddAttribute(const char name[], const char value[]) |
- { |
+ |
+ bool onAddAttribute(const char name[], const char value[]) override { |
SkDOM::Attr* attr = fAttrs.append(); |
attr->fName = dupstr(fAlloc, name); |
attr->fValue = dupstr(fAlloc, value); |
return false; |
} |
- virtual bool onEndElement(const char elem[]) |
- { |
+ |
+ bool onEndElement(const char elem[]) override { |
--fLevel; |
if (fNeedToFlush) |
this->flushAttributes(); |
@@ -279,20 +279,40 @@ protected: |
parent->fFirstChild = prev; |
return false; |
} |
+ |
+ bool onText(const char text[], int len) override { |
+ SkString str(text, len); |
+ this->startCommon(str.c_str(), SkDOM::kText_Type); |
+ this->SkDOMParser::onEndElement(str.c_str()); |
+ |
+ return false; |
+ } |
+ |
private: |
+ void startCommon(const char elem[], SkDOM::Type type) { |
+ if (fLevel > 0 && fNeedToFlush) |
+ this->flushAttributes(); |
+ |
+ fNeedToFlush = true; |
+ fElemName = dupstr(fAlloc, elem); |
+ fElemType = type; |
+ ++fLevel; |
+ } |
+ |
SkTDArray<SkDOM::Node*> fParentStack; |
- SkChunkAlloc* fAlloc; |
- SkDOM::Node* fRoot; |
+ SkChunkAlloc* fAlloc; |
+ SkDOM::Node* fRoot; |
+ bool fNeedToFlush; |
// state needed for flushAttributes() |
SkTDArray<SkDOM::Attr> fAttrs; |
char* fElemName; |
+ SkDOM::Type fElemType; |
int fLevel; |
}; |
const SkDOM::Node* SkDOM::build(const char doc[], size_t len) |
{ |
- fAlloc.reset(); |
SkDOMParser parser(&fAlloc); |
if (!parser.parse(doc, len)) |
{ |
@@ -310,6 +330,11 @@ const SkDOM::Node* SkDOM::build(const char doc[], size_t len) |
static void walk_dom(const SkDOM& dom, const SkDOM::Node* node, SkXMLParser* parser) |
{ |
const char* elem = dom.getName(node); |
+ if (dom.getType(node) == SkDOM::kText_Type) { |
+ SkASSERT(dom.countChildren(node) == 0); |
+ parser->text(elem, SkToInt(strlen(elem))); |
+ return; |
+ } |
parser->startElement(elem); |
@@ -331,7 +356,6 @@ static void walk_dom(const SkDOM& dom, const SkDOM::Node* node, SkXMLParser* par |
const SkDOM::Node* SkDOM::copy(const SkDOM& dom, const SkDOM::Node* node) |
{ |
- fAlloc.reset(); |
SkDOMParser parser(&fAlloc); |
walk_dom(dom, node, &parser); |
@@ -340,6 +364,21 @@ const SkDOM::Node* SkDOM::copy(const SkDOM& dom, const SkDOM::Node* node) |
return fRoot; |
} |
+SkXMLParser* SkDOM::beginParsing() { |
+ SkASSERT(!fParser); |
+ fParser.reset(SkNEW_ARGS(SkDOMParser, (&fAlloc))); |
+ |
+ return fParser.get(); |
+} |
+ |
+const SkDOM::Node* SkDOM::finishParsing() { |
+ SkASSERT(fParser); |
+ fRoot = fParser->getRoot(); |
+ fParser.free(); |
+ |
+ return fRoot; |
+} |
+ |
////////////////////////////////////////////////////////////////////////// |
int SkDOM::countChildren(const Node* node, const char elem[]) const |
@@ -427,41 +466,14 @@ bool SkDOM::hasBool(const Node* node, const char name[], bool target) const |
#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"); |
- } |
+ SkDebugWStream debugStream; |
+ SkXMLStreamWriter xmlWriter(&debugStream); |
+ xmlWriter.writeDOM(*this, node, false); |
} |
void SkDOM::UnitTest() |