1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#include "SkXMLParser.h"
11#include "SkString.h"
12#include "SkStream.h"
13
14#include "expat.h"
15
16#ifdef SK_BUILD_FOR_PPI
17#define CHAR_16_TO_9
18#endif
19
20#if defined CHAR_16_TO_9
21inline size_t sk_wcslen(const short* char16) {
22    const short* start = char16;
23    while (*char16)
24        char16++;
25    return char16 - start;
26}
27
28inline const char* ConvertUnicodeToChar(const short* ch16, size_t len, SkAutoMalloc& ch8Malloc) {
29    char* ch8 = (char*) ch8Malloc.get();
30    int index;
31    for (index = 0; index < len; index++)
32        ch8[index] = (char) ch16[index];
33    ch8[index] = '\0';
34    return ch8;
35}
36#endif
37
38static void XMLCALL start_proc(void *data, const char *el, const char **attr)
39{
40#if defined CHAR_16_TO_9
41    size_t len = sk_wcslen((const short*) el);
42    SkAutoMalloc    el8(len + 1);
43    el = ConvertUnicodeToChar((const short*) el, len, el8);
44#endif
45    if (((SkXMLParser*)data)->startElement(el)) {
46        XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false);
47        return;
48    }
49    while (*attr)
50    {
51        const char* attr0 = attr[0];
52        const char* attr1 = attr[1];
53#if defined CHAR_16_TO_9
54        size_t len0 = sk_wcslen((const short*) attr0);
55        SkAutoMalloc    attr0_8(len0 + 1);
56        attr0 = ConvertUnicodeToChar((const short*) attr0, len0, attr0_8);
57        size_t len1 = sk_wcslen((const short*) attr1);
58        SkAutoMalloc    attr1_8(len1 + 1);
59        attr1 = ConvertUnicodeToChar((const short*) attr1, len1, attr1_8);
60#endif
61        if (((SkXMLParser*)data)->addAttribute(attr0, attr1)) {
62            XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false);
63            return;
64        }
65        attr += 2;
66    }
67}
68
69static void XMLCALL end_proc(void *data, const char *el)
70{
71#if defined CHAR_16_TO_9
72    size_t len = sk_wcslen((const short*) el);
73    SkAutoMalloc    el8(len + 1);
74    el = ConvertUnicodeToChar((const short*) el, len, el8);
75#endif
76    if (((SkXMLParser*)data)->endElement(el))
77        XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false);
78}
79
80static void XMLCALL text_proc(void* data, const char* text, int len)
81{
82#if defined CHAR_16_TO_9
83    SkAutoMalloc    text8(len + 1);
84    text = ConvertUnicodeToChar((const short*) text, len, text8);
85#endif
86    if (((SkXMLParser*)data)->text(text, len))
87        XML_StopParser((XML_Parser) ((SkXMLParser*)data)->fParser, false);
88}
89
90bool SkXMLParser::parse(const char doc[], size_t len)
91{
92    if (len == 0) {
93        fError->fCode = SkXMLParserError::kEmptyFile;
94        reportError(NULL);
95        return false;
96    }
97    XML_Parser p = XML_ParserCreate(NULL);
98    SkASSERT(p);
99    fParser = p;
100    XML_SetElementHandler(p, start_proc, end_proc);
101    XML_SetCharacterDataHandler(p, text_proc);
102    XML_SetUserData(p, this);
103
104    bool success = true;
105    int error = XML_Parse(p, doc, len, true);
106    if (error == XML_STATUS_ERROR) {
107        reportError(p);
108        success = false;
109    }
110    XML_ParserFree(p);
111    return success;
112}
113
114bool SkXMLParser::parse(SkStream& input)
115{
116    size_t          len = input.getLength();
117    SkAutoMalloc    am(len);
118    char*           doc = (char*)am.get();
119
120    input.rewind();
121    size_t  len2 = input.read(doc, len);
122    SkASSERT(len2 == len);
123
124    return this->parse(doc, len2);
125}
126
127void SkXMLParser::reportError(void* p)
128{
129    XML_Parser parser = (XML_Parser) p;
130    if (fError && parser) {
131        fError->fNativeCode = XML_GetErrorCode(parser);
132        fError->fLineNumber = XML_GetCurrentLineNumber(parser);
133    }
134}
135
136void SkXMLParser::GetNativeErrorString(int error, SkString* str)
137{
138    if (str)
139        str->set(XML_ErrorString((XML_Error) error));
140}
141