Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(108)

Side by Side Diff: src/xml/SkXMLParser.cpp

Issue 2154853002: [SkXMLParser] Initial text node support (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: buffered text Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | tests/SkDOMTest.cpp » ('j') | tests/SkDOMTest.cpp » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2006 The Android Open Source Project 2 * Copyright 2006 The Android Open Source Project
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "expat.h" 8 #include "expat.h"
9 9
10 #include "SkStream.h" 10 #include "SkStream.h"
11 #include "SkString.h"
12 #include "SkTypes.h"
11 #include "SkXMLParser.h" 13 #include "SkXMLParser.h"
12 14
13 static char const* const gErrorStrings[] = { 15 static char const* const gErrorStrings[] = {
14 "empty or missing file ", 16 "empty or missing file ",
15 "unknown element ", 17 "unknown element ",
16 "unknown attribute name ", 18 "unknown attribute name ",
17 "error in attribute value ", 19 "error in attribute value ",
18 "duplicate ID ", 20 "duplicate ID ",
19 "unknown error " 21 "unknown error "
20 }; 22 };
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 //////////////// 54 ////////////////
53 55
54 namespace { 56 namespace {
55 57
56 const XML_Memory_Handling_Suite sk_XML_alloc = { 58 const XML_Memory_Handling_Suite sk_XML_alloc = {
57 sk_malloc_throw, 59 sk_malloc_throw,
58 sk_realloc_throw, 60 sk_realloc_throw,
59 sk_free 61 sk_free
60 }; 62 };
61 63
64 struct ParsingContext {
65 ParsingContext(SkXMLParser* parser)
66 : fParser(parser)
67 , fXMLParser(XML_ParserCreate_MM(nullptr, &sk_XML_alloc, nullptr)) { }
68
69 void flushText() {
70 if (!fBufferedText.isEmpty()) {
71 fParser->text(fBufferedText.c_str(), SkTo<int>(fBufferedText.size()) );
72 fBufferedText.reset();
73 }
74 }
75
76 SkXMLParser* fParser;
77 SkAutoTCallVProc<skstd::remove_pointer_t<XML_Parser>, XML_ParserFree> fXMLPa rser;
robertphillips 2016/07/18 15:29:18 private: ?
f(malita) 2016/07/18 17:36:32 Done.
78 SkString fBufferedText;
79 };
80
62 void XMLCALL start_element_handler(void *data, const char* tag, const char** att ributes) { 81 void XMLCALL start_element_handler(void *data, const char* tag, const char** att ributes) {
63 SkXMLParser* parser = static_cast<SkXMLParser*>(data); 82 ParsingContext* ctx = static_cast<ParsingContext*>(data);
83 ctx->flushText();
64 84
65 parser->startElement(tag); 85 ctx->fParser->startElement(tag);
66 86
67 for (size_t i = 0; attributes[i]; i += 2) { 87 for (size_t i = 0; attributes[i]; i += 2) {
68 parser->addAttribute(attributes[i], attributes[i + 1]); 88 ctx->fParser->addAttribute(attributes[i], attributes[i + 1]);
69 } 89 }
70 } 90 }
71 91
72 void XMLCALL end_element_handler(void* data, const char* tag) { 92 void XMLCALL end_element_handler(void* data, const char* tag) {
73 static_cast<SkXMLParser*>(data)->endElement(tag); 93 ParsingContext* ctx = static_cast<ParsingContext*>(data);
94 ctx->flushText();
95 ctx->fParser->endElement(tag);
96 }
97
98 void XMLCALL text_handler(void *data, const char* txt, int len) {
robertphillips 2016/07/18 15:29:18 Should be have a macro like "HANDLER_PREAMBLE(ctx)
f(malita) 2016/07/18 17:36:32 Done.
99 ParsingContext* ctx = static_cast<ParsingContext*>(data);
100 ctx->fBufferedText.append(txt, len);
101 }
102
103 void XMLCALL entity_decl_handler(void *data,
104 const XML_Char *entityName,
105 int is_parameter_entity,
106 const XML_Char *value,
107 int value_length,
108 const XML_Char *base,
109 const XML_Char *systemId,
110 const XML_Char *publicId,
111 const XML_Char *notationName) {
112 ParsingContext* ctx = static_cast<ParsingContext*>(data);
113
114 SkDebugf("'%s' entity declaration found, stopping processing", entityName);
115 XML_StopParser(ctx->fXMLParser, XML_FALSE);
74 } 116 }
75 117
76 } // anonymous namespace 118 } // anonymous namespace
77 119
78 SkXMLParser::SkXMLParser(SkXMLParserError* parserError) : fParser(nullptr), fErr or(parserError) 120 SkXMLParser::SkXMLParser(SkXMLParserError* parserError) : fParser(nullptr), fErr or(parserError)
79 { 121 {
80 } 122 }
81 123
82 SkXMLParser::~SkXMLParser() 124 SkXMLParser::~SkXMLParser()
83 { 125 {
84 } 126 }
85 127
86 bool SkXMLParser::parse(SkStream& docStream) 128 bool SkXMLParser::parse(SkStream& docStream)
87 { 129 {
88 SkAutoTCallVProc<skstd::remove_pointer_t<XML_Parser>, XML_ParserFree> 130 ParsingContext ctx(this);
89 parser(XML_ParserCreate_MM(nullptr, &sk_XML_alloc, nullptr)); 131 if (!ctx.fXMLParser) {
90 if (!parser) {
91 SkDebugf("could not create XML parser\n"); 132 SkDebugf("could not create XML parser\n");
92 return false; 133 return false;
93 } 134 }
94 135
95 XML_SetUserData(parser, this); 136 XML_SetUserData(ctx.fXMLParser, &ctx);
96 XML_SetElementHandler(parser, start_element_handler, end_element_handler); 137 XML_SetElementHandler(ctx.fXMLParser, start_element_handler, end_element_han dler);
138 XML_SetCharacterDataHandler(ctx.fXMLParser, text_handler);
139
140 // Disable entity processing, to inhibit internal entity expansion. See expa t CVE-2013-0340.
141 XML_SetEntityDeclHandler(ctx.fXMLParser, entity_decl_handler);
97 142
98 static const int kBufferSize = 512 SkDEBUGCODE( - 507); 143 static const int kBufferSize = 512 SkDEBUGCODE( - 507);
99 bool done = false; 144 bool done = false;
100 do { 145 do {
101 void* buffer = XML_GetBuffer(parser, kBufferSize); 146 void* buffer = XML_GetBuffer(ctx.fXMLParser, kBufferSize);
102 if (!buffer) { 147 if (!buffer) {
103 SkDebugf("could not buffer enough to continue\n"); 148 SkDebugf("could not buffer enough to continue\n");
104 return false; 149 return false;
105 } 150 }
106 151
107 size_t len = docStream.read(buffer, kBufferSize); 152 size_t len = docStream.read(buffer, kBufferSize);
108 done = docStream.isAtEnd(); 153 done = docStream.isAtEnd();
109 XML_Status status = XML_ParseBuffer(parser, SkToS32(len), done); 154 XML_Status status = XML_ParseBuffer(ctx.fXMLParser, SkToS32(len), done);
110 if (XML_STATUS_ERROR == status) { 155 if (XML_STATUS_ERROR == status) {
111 XML_Error error = XML_GetErrorCode(parser); 156 XML_Error error = XML_GetErrorCode(ctx.fXMLParser);
112 int line = XML_GetCurrentLineNumber(parser); 157 int line = XML_GetCurrentLineNumber(ctx.fXMLParser);
113 int column = XML_GetCurrentColumnNumber(parser); 158 int column = XML_GetCurrentColumnNumber(ctx.fXMLParser);
114 const XML_LChar* errorString = XML_ErrorString(error); 159 const XML_LChar* errorString = XML_ErrorString(error);
115 SkDebugf("parse error @%d:%d: %d (%s).\n", line, column, error, erro rString); 160 SkDebugf("parse error @%d:%d: %d (%s).\n", line, column, error, erro rString);
116 return false; 161 return false;
117 } 162 }
118 } while (!done); 163 } while (!done);
119 164
120 return true; 165 return true;
121 } 166 }
122 167
123 bool SkXMLParser::parse(const char doc[], size_t len) 168 bool SkXMLParser::parse(const char doc[], size_t len)
(...skipping 26 matching lines...) Expand all
150 { 195 {
151 return this->onText(text, len); 196 return this->onText(text, len);
152 } 197 }
153 198
154 //////////////////////////////////////////////////////////////////////////////// 199 ////////////////////////////////////////////////////////////////////////////////
155 200
156 bool SkXMLParser::onStartElement(const char elem[]) {return false; } 201 bool SkXMLParser::onStartElement(const char elem[]) {return false; }
157 bool SkXMLParser::onAddAttribute(const char name[], const char value[]) {return false; } 202 bool SkXMLParser::onAddAttribute(const char name[], const char value[]) {return false; }
158 bool SkXMLParser::onEndElement(const char elem[]) { return false; } 203 bool SkXMLParser::onEndElement(const char elem[]) { return false; }
159 bool SkXMLParser::onText(const char text[], int len) {return false; } 204 bool SkXMLParser::onText(const char text[], int len) {return false; }
OLDNEW
« no previous file with comments | « no previous file | tests/SkDOMTest.cpp » ('j') | tests/SkDOMTest.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698