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
sk_wcslen(const short * char16)21 inline size_t sk_wcslen(const short* char16) {
22 const short* start = char16;
23 while (*char16)
24 char16++;
25 return char16 - start;
26 }
27
ConvertUnicodeToChar(const short * ch16,size_t len,SkAutoMalloc & ch8Malloc)28 inline 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
start_proc(void * data,const char * el,const char ** attr)38 static 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
end_proc(void * data,const char * el)69 static 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
text_proc(void * data,const char * text,int len)80 static 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
parse(const char doc[],size_t len)90 bool 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
parse(SkStream & input)114 bool SkXMLParser::parse(SkStream& input)
115 {
116 size_t len = input.read(NULL, 0);
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
reportError(void * p)127 void 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
GetNativeErrorString(int error,SkString * str)136 void SkXMLParser::GetNativeErrorString(int error, SkString* str)
137 {
138 if (str)
139 str->set(XML_ErrorString((XML_Error) error));
140 }
141
142