aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/xml
diff options
context:
space:
mode:
authorGravatar fmalita <fmalita@chromium.org>2016-07-14 19:14:06 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-07-14 19:14:06 -0700
commit7445e86bac478dea91da32473e5a01baff637c23 (patch)
tree8bcb373c49d64579f87bc57b4270b82ad0838fec /src/xml
parent59779ae8ce316bf8b8082ec2df1683ccd38161f1 (diff)
Dust-off SkXMLParser
Hook up SkXMLParser to Expat, such that it can actually parse, err, XML. Add a trivial unit test. R=robertphillips@google.com,reed@google.com GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2142893006 Review-Url: https://codereview.chromium.org/2142893006
Diffstat (limited to 'src/xml')
-rw-r--r--src/xml/SkDOM.cpp46
-rw-r--r--src/xml/SkXMLParser.cpp64
2 files changed, 68 insertions, 42 deletions
diff --git a/src/xml/SkDOM.cpp b/src/xml/SkDOM.cpp
index 15b458e4fb..78cf6f07e9 100644
--- a/src/xml/SkDOM.cpp
+++ b/src/xml/SkDOM.cpp
@@ -310,10 +310,9 @@ private:
int fLevel;
};
-const SkDOM::Node* SkDOM::build(const char doc[], size_t len)
-{
+const SkDOM::Node* SkDOM::build(SkStream& docStream) {
SkDOMParser parser(&fAlloc);
- if (!parser.parse(doc, len))
+ if (!parser.parse(docStream))
{
SkDEBUGCODE(SkDebugf("xml parse error, line %d\n", parser.fParserError.getLineNumber());)
fRoot = nullptr;
@@ -324,6 +323,11 @@ const SkDOM::Node* SkDOM::build(const char doc[], size_t len)
return fRoot;
}
+const SkDOM::Node* SkDOM::build(const char doc[], size_t len) {
+ SkMemoryStream docStream(doc, len);
+ return this->build(docStream);
+}
+
///////////////////////////////////////////////////////////////////////////
static void walk_dom(const SkDOM& dom, const SkDOM::Node* node, SkXMLParser* parser)
@@ -475,40 +479,4 @@ void SkDOM::dump(const Node* node, int level) const
xmlWriter.writeDOM(*this, node, false);
}
-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() == nullptr);
-
- 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 == nullptr);
-
- SkASSERT(dom.getFirstChild(root, "elem1"));
- SkASSERT(!dom.getFirstChild(root, "subelem1"));
-
- dom.dump();
-#endif
-}
-
#endif
diff --git a/src/xml/SkXMLParser.cpp b/src/xml/SkXMLParser.cpp
index 11f4c6bf72..77903cbb05 100644
--- a/src/xml/SkXMLParser.cpp
+++ b/src/xml/SkXMLParser.cpp
@@ -5,7 +5,9 @@
* found in the LICENSE file.
*/
+#include "expat.h"
+#include "SkStream.h"
#include "SkXMLParser.h"
static char const* const gErrorStrings[] = {
@@ -47,9 +49,32 @@ void SkXMLParserError::reset() {
fNativeCode = -1;
}
-
////////////////
+namespace {
+
+const XML_Memory_Handling_Suite sk_XML_alloc = {
+ sk_malloc_throw,
+ sk_realloc_throw,
+ sk_free
+};
+
+void XMLCALL start_element_handler(void *data, const char* tag, const char** attributes) {
+ SkXMLParser* parser = static_cast<SkXMLParser*>(data);
+
+ parser->startElement(tag);
+
+ for (size_t i = 0; attributes[i]; i += 2) {
+ parser->addAttribute(attributes[i], attributes[i + 1]);
+ }
+}
+
+void XMLCALL end_element_handler(void* data, const char* tag) {
+ static_cast<SkXMLParser*>(data)->endElement(tag);
+}
+
+} // anonymous namespace
+
SkXMLParser::SkXMLParser(SkXMLParserError* parserError) : fParser(nullptr), fError(parserError)
{
}
@@ -60,12 +85,45 @@ SkXMLParser::~SkXMLParser()
bool SkXMLParser::parse(SkStream& docStream)
{
- return false;
+ SkAutoTCallVProc<skstd::remove_pointer_t<XML_Parser>, XML_ParserFree>
+ parser(XML_ParserCreate_MM(nullptr, &sk_XML_alloc, nullptr));
+ if (!parser) {
+ SkDebugf("could not create XML parser\n");
+ return false;
+ }
+
+ XML_SetUserData(parser, this);
+ XML_SetElementHandler(parser, start_element_handler, end_element_handler);
+
+ static const int kBufferSize = 512 SkDEBUGCODE( - 507);
+ bool done = false;
+ do {
+ void* buffer = XML_GetBuffer(parser, kBufferSize);
+ if (!buffer) {
+ SkDebugf("could not buffer enough to continue\n");
+ return false;
+ }
+
+ size_t len = docStream.read(buffer, kBufferSize);
+ done = docStream.isAtEnd();
+ XML_Status status = XML_ParseBuffer(parser, SkToS32(len), done);
+ if (XML_STATUS_ERROR == status) {
+ XML_Error error = XML_GetErrorCode(parser);
+ int line = XML_GetCurrentLineNumber(parser);
+ int column = XML_GetCurrentColumnNumber(parser);
+ const XML_LChar* errorString = XML_ErrorString(error);
+ SkDebugf("parse error @%d:%d: %d (%s).\n", line, column, error, errorString);
+ return false;
+ }
+ } while (!done);
+
+ return true;
}
bool SkXMLParser::parse(const char doc[], size_t len)
{
- return false;
+ SkMemoryStream docStream(doc, len);
+ return this->parse(docStream);
}
void SkXMLParser::GetNativeErrorString(int error, SkString* str)