20 "empty or missing file ",
22 "unknown attribute name ",
23 "error in attribute value ",
62constexpr const void* kHashSeed = &kHashSeed;
70struct ParsingContext {
73 , fXMLParser(XML_ParserCreate_MM(nullptr, &
sk_XML_alloc, nullptr)) { }
76 if (!fBufferedText.empty()) {
77 fParser->text(fBufferedText.data(), SkTo<int>(fBufferedText.size()));
78 fBufferedText.clear();
82 void appendText(
const char*
txt,
size_t len) {
83 fBufferedText.insert(fBufferedText.end(),
txt, &
txt[len]);
90 std::vector<char> fBufferedText;
93#define HANDLER_CONTEXT(arg, name) ParsingContext* name = static_cast<ParsingContext*>(arg)
99 ctx->fParser->startElement(tag);
101 for (
size_t i = 0; attributes[i]; i += 2) {
102 ctx->fParser->addAttribute(attributes[i], attributes[i + 1]);
110 ctx->fParser->endElement(tag);
113void XMLCALL text_handler(
void *data,
const char*
txt,
int len) {
116 ctx->appendText(
txt, SkTo<size_t>(len));
119void XMLCALL entity_decl_handler(
void *data,
120 const XML_Char *entityName,
121 int is_parameter_entity,
122 const XML_Char *value,
124 const XML_Char *
base,
125 const XML_Char *systemId,
126 const XML_Char *publicId,
127 const XML_Char *notationName) {
130 SkDEBUGF(
"'%s' entity declaration found, stopping processing", entityName);
131 XML_StopParser(ctx->fXMLParser, XML_FALSE);
146 ParsingContext ctx(
this);
147 if (!ctx.fXMLParser) {
148 SkDEBUGF(
"could not create XML parser\n");
155 unsigned long seed =
static_cast<unsigned long>(
156 reinterpret_cast<size_t>(kHashSeed) & 0xFFFFFFFF);
157 XML_SetHashSalt(ctx.fXMLParser, seed ? seed : 1);
159 XML_SetUserData(ctx.fXMLParser, &ctx);
161 XML_SetCharacterDataHandler(ctx.fXMLParser, text_handler);
164 XML_SetEntityDeclHandler(ctx.fXMLParser, entity_decl_handler);
166 XML_Status status = XML_STATUS_OK;
169 status = XML_Parse(ctx.fXMLParser,
179 SkDEBUGF(
"could not buffer enough to continue\n");
185 status = XML_ParseBuffer(ctx.fXMLParser,
SkToS32(len),
done);
186 if (XML_STATUS_ERROR == status) {
191 if (XML_STATUS_ERROR == status) {
193 XML_Error
error = XML_GetErrorCode(ctx.fXMLParser);
194 int line = XML_GetCurrentLineNumber(ctx.fXMLParser);
195 int column = XML_GetCurrentColumnNumber(ctx.fXMLParser);
196 const XML_LChar* errorString = XML_ErrorString(
error);
197 SkDEBUGF(
"parse error @%d:%d: %d (%s).\n", line, column,
error, errorString);
208 return this->
parse(docStream);
233 return this->
onText(text, len);
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
static void XMLCALL start_element_handler(void *data, const char *tag, const char **attributes)
static void XMLCALL end_element_handler(void *data, const char *tag)
static const XML_Memory_Handling_Suite sk_XML_alloc
SK_API void sk_free(void *)
static void * sk_malloc_throw(size_t size)
SK_API void * sk_realloc_throw(void *buffer, size_t size)
static const size_t kBufferSize
constexpr int32_t SkToS32(S x)
#define HANDLER_CONTEXT(arg, name)
static char const *const gErrorStrings[]
virtual size_t getPosition() const
virtual bool isAtEnd() const =0
virtual size_t getLength() const
virtual const void * getMemoryBase()
virtual bool hasLength() const
virtual size_t read(void *buffer, size_t size)=0
void set(const SkString &src)
void append(const char text[])
virtual ~SkXMLParserError()
virtual void getErrorString(SkString *str) const
bool startElement(const char elem[])
bool endElement(const char elem[])
virtual bool onEndElement(const char elem[])
static void GetNativeErrorString(int nativeErrorCode, SkString *str)
virtual bool onAddAttribute(const char name[], const char value[])
virtual bool onText(const char text[], int len)
virtual bool onStartElement(const char elem[])
bool addAttribute(const char name[], const char value[])
bool text(const char text[], int len)
bool parse(const char doc[], size_t len)
SkXMLParser(SkXMLParserError *parserError=nullptr)
static const uint8_t buffer[]
const uint8_t uint32_t uint32_t GError ** error