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