11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/* 31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2006 The Android Open Source Project 41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * 51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file. 71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */ 81cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkXMLParser.h" 110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkString.h" 120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkStream.h" 130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "expat.h" 150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_BUILD_FOR_PPI 170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define CHAR_16_TO_9 180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if defined CHAR_16_TO_9 210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectinline size_t sk_wcslen(const short* char16) { 220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const short* start = char16; 230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while (*char16) 240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project char16++; 250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return char16 - start; 260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectinline const char* ConvertUnicodeToChar(const short* ch16, size_t len, SkAutoMalloc& ch8Malloc) { 290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project char* ch8 = (char*) ch8Malloc.get(); 300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int index; 310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (index = 0; index < len; index++) 320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ch8[index] = (char) ch16[index]; 330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ch8[index] = '\0'; 340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return ch8; 350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void XMLCALL start_proc(void *data, const char *el, const char **attr) 390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ 400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if defined CHAR_16_TO_9 410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size_t len = sk_wcslen((const short*) el); 420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoMalloc el8(len + 1); 430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project el = ConvertUnicodeToChar((const short*) el, len, el8); 440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (((SkXMLParser*)data)->startElement(el)) { 460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false); 470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while (*attr) 500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const char* attr0 = attr[0]; 520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const char* attr1 = attr[1]; 530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if defined CHAR_16_TO_9 540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size_t len0 = sk_wcslen((const short*) attr0); 550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoMalloc attr0_8(len0 + 1); 560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project attr0 = ConvertUnicodeToChar((const short*) attr0, len0, attr0_8); 570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size_t len1 = sk_wcslen((const short*) attr1); 580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoMalloc attr1_8(len1 + 1); 590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project attr1 = ConvertUnicodeToChar((const short*) attr1, len1, attr1_8); 600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (((SkXMLParser*)data)->addAttribute(attr0, attr1)) { 620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false); 630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project attr += 2; 660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void XMLCALL end_proc(void *data, const char *el) 700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ 710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if defined CHAR_16_TO_9 720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size_t len = sk_wcslen((const short*) el); 730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoMalloc el8(len + 1); 740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project el = ConvertUnicodeToChar((const short*) el, len, el8); 750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (((SkXMLParser*)data)->endElement(el)) 770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false); 780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void XMLCALL text_proc(void* data, const char* text, int len) 810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ 820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if defined CHAR_16_TO_9 830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoMalloc text8(len + 1); 840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project text = ConvertUnicodeToChar((const short*) text, len, text8); 850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (((SkXMLParser*)data)->text(text, len)) 870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false); 880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkXMLParser::parse(const char doc[], size_t len) 910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ 920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (len == 0) { 930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fError->fCode = SkXMLParserError::kEmptyFile; 940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project reportError(NULL); 950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project XML_Parser p = XML_ParserCreate(NULL); 980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(p); 990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fParser = p; 1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project XML_SetElementHandler(p, start_proc, end_proc); 1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project XML_SetCharacterDataHandler(p, text_proc); 1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project XML_SetUserData(p, this); 1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool success = true; 1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int error = XML_Parse(p, doc, len, true); 1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (error == XML_STATUS_ERROR) { 1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project reportError(p); 1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project success = false; 1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project XML_ParserFree(p); 1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return success; 1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkXMLParser::parse(SkStream& input) 1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ 1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size_t len = input.read(NULL, 0); 1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoMalloc am(len); 1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project char* doc = (char*)am.get(); 1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project input.rewind(); 1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size_t len2 = input.read(doc, len); 1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(len2 == len); 1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return this->parse(doc, len2); 1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkXMLParser::reportError(void* p) 1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ 1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project XML_Parser parser = (XML_Parser) p; 1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fError && parser) { 1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fError->fNativeCode = XML_GetErrorCode(parser); 1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fError->fLineNumber = XML_GetCurrentLineNumber(parser); 1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkXMLParser::GetNativeErrorString(int error, SkString* str) 1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ 1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (str) 1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project str->set(XML_ErrorString((XML_Error) error)); 1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 142