diff options
Diffstat (limited to 'src/xml')
-rw-r--r-- | src/xml/SkDOM.cpp | 46 | ||||
-rw-r--r-- | src/xml/SkXMLParser.cpp | 64 |
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) |