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