michael@0: michael@0: /* michael@0: * Copyright 2006 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #include "SkXMLParser.h" michael@0: #include "SkString.h" michael@0: #include "SkStream.h" michael@0: michael@0: #include "expat.h" michael@0: michael@0: #ifdef SK_BUILD_FOR_PPI michael@0: #define CHAR_16_TO_9 michael@0: #endif michael@0: michael@0: #if defined CHAR_16_TO_9 michael@0: inline size_t sk_wcslen(const short* char16) { michael@0: const short* start = char16; michael@0: while (*char16) michael@0: char16++; michael@0: return char16 - start; michael@0: } michael@0: michael@0: inline const char* ConvertUnicodeToChar(const short* ch16, size_t len, SkAutoMalloc& ch8Malloc) { michael@0: char* ch8 = (char*) ch8Malloc.get(); michael@0: int index; michael@0: for (index = 0; index < len; index++) michael@0: ch8[index] = (char) ch16[index]; michael@0: ch8[index] = '\0'; michael@0: return ch8; michael@0: } michael@0: #endif michael@0: michael@0: static void XMLCALL start_proc(void *data, const char *el, const char **attr) michael@0: { michael@0: #if defined CHAR_16_TO_9 michael@0: size_t len = sk_wcslen((const short*) el); michael@0: SkAutoMalloc el8(len + 1); michael@0: el = ConvertUnicodeToChar((const short*) el, len, el8); michael@0: #endif michael@0: if (((SkXMLParser*)data)->startElement(el)) { michael@0: XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false); michael@0: return; michael@0: } michael@0: while (*attr) michael@0: { michael@0: const char* attr0 = attr[0]; michael@0: const char* attr1 = attr[1]; michael@0: #if defined CHAR_16_TO_9 michael@0: size_t len0 = sk_wcslen((const short*) attr0); michael@0: SkAutoMalloc attr0_8(len0 + 1); michael@0: attr0 = ConvertUnicodeToChar((const short*) attr0, len0, attr0_8); michael@0: size_t len1 = sk_wcslen((const short*) attr1); michael@0: SkAutoMalloc attr1_8(len1 + 1); michael@0: attr1 = ConvertUnicodeToChar((const short*) attr1, len1, attr1_8); michael@0: #endif michael@0: if (((SkXMLParser*)data)->addAttribute(attr0, attr1)) { michael@0: XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false); michael@0: return; michael@0: } michael@0: attr += 2; michael@0: } michael@0: } michael@0: michael@0: static void XMLCALL end_proc(void *data, const char *el) michael@0: { michael@0: #if defined CHAR_16_TO_9 michael@0: size_t len = sk_wcslen((const short*) el); michael@0: SkAutoMalloc el8(len + 1); michael@0: el = ConvertUnicodeToChar((const short*) el, len, el8); michael@0: #endif michael@0: if (((SkXMLParser*)data)->endElement(el)) michael@0: XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false); michael@0: } michael@0: michael@0: static void XMLCALL text_proc(void* data, const char* text, int len) michael@0: { michael@0: #if defined CHAR_16_TO_9 michael@0: SkAutoMalloc text8(len + 1); michael@0: text = ConvertUnicodeToChar((const short*) text, len, text8); michael@0: #endif michael@0: if (((SkXMLParser*)data)->text(text, len)) michael@0: XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false); michael@0: } michael@0: michael@0: bool SkXMLParser::parse(const char doc[], size_t len) michael@0: { michael@0: if (len == 0) { michael@0: fError->fCode = SkXMLParserError::kEmptyFile; michael@0: reportError(NULL); michael@0: return false; michael@0: } michael@0: XML_Parser p = XML_ParserCreate(NULL); michael@0: SkASSERT(p); michael@0: fParser = p; michael@0: XML_SetElementHandler(p, start_proc, end_proc); michael@0: XML_SetCharacterDataHandler(p, text_proc); michael@0: XML_SetUserData(p, this); michael@0: michael@0: bool success = true; michael@0: int error = XML_Parse(p, doc, len, true); michael@0: if (error == XML_STATUS_ERROR) { michael@0: reportError(p); michael@0: success = false; michael@0: } michael@0: XML_ParserFree(p); michael@0: return success; michael@0: } michael@0: michael@0: bool SkXMLParser::parse(SkStream& input) michael@0: { michael@0: size_t len = input.getLength(); michael@0: SkAutoMalloc am(len); michael@0: char* doc = (char*)am.get(); michael@0: michael@0: input.rewind(); michael@0: size_t len2 = input.read(doc, len); michael@0: SkASSERT(len2 == len); michael@0: michael@0: return this->parse(doc, len2); michael@0: } michael@0: michael@0: void SkXMLParser::reportError(void* p) michael@0: { michael@0: XML_Parser parser = (XML_Parser) p; michael@0: if (fError && parser) { michael@0: fError->fNativeCode = XML_GetErrorCode(parser); michael@0: fError->fLineNumber = XML_GetCurrentLineNumber(parser); michael@0: } michael@0: } michael@0: michael@0: void SkXMLParser::GetNativeErrorString(int error, SkString* str) michael@0: { michael@0: if (str) michael@0: str->set(XML_ErrorString((XML_Error) error)); michael@0: }