blob: 7a07c06c41e1128809a829bd404f86dcf8be1dd6 [file] [log] [blame]
Adam Lesinski769de982015-04-10 19:43:55 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "BinaryXmlPullParser.h"
18
19#include <androidfw/ResourceTypes.h>
20#include <memory>
21#include <string>
22#include <vector>
23
24namespace aapt {
25
26static XmlPullParser::Event codeToEvent(android::ResXMLParser::event_code_t code) {
27 switch (code) {
28 case android::ResXMLParser::START_DOCUMENT:
29 return XmlPullParser::Event::kStartDocument;
30 case android::ResXMLParser::END_DOCUMENT:
31 return XmlPullParser::Event::kEndDocument;
32 case android::ResXMLParser::START_NAMESPACE:
33 return XmlPullParser::Event::kStartNamespace;
34 case android::ResXMLParser::END_NAMESPACE:
35 return XmlPullParser::Event::kEndNamespace;
36 case android::ResXMLParser::START_TAG:
37 return XmlPullParser::Event::kStartElement;
38 case android::ResXMLParser::END_TAG:
39 return XmlPullParser::Event::kEndElement;
40 case android::ResXMLParser::TEXT:
41 return XmlPullParser::Event::kText;
42 default:
43 break;
44 }
45 return XmlPullParser::Event::kBadDocument;
46}
47
48BinaryXmlPullParser::BinaryXmlPullParser(const std::shared_ptr<android::ResXMLTree>& parser)
49 : mParser(parser), mEvent(Event::kStartDocument), mHasComment(false), sEmpty(), sEmpty8(),
50 mDepth(0) {
51}
52
53XmlPullParser::Event BinaryXmlPullParser::next() {
54 mStr1.clear();
55 mStr2.clear();
56 mAttributes.clear();
57
58 android::ResXMLParser::event_code_t code;
59 if (mHasComment) {
60 mHasComment = false;
61 code = mParser->getEventType();
62 } else {
63 code = mParser->next();
64 if (code != android::ResXMLParser::BAD_DOCUMENT) {
65 size_t len;
66 const char16_t* comment = mParser->getComment(&len);
67 if (comment) {
68 mHasComment = true;
69 mStr1.assign(comment, len);
70 return XmlPullParser::Event::kComment;
71 }
72 }
73 }
74
75 size_t len;
76 const char16_t* data;
77 mEvent = codeToEvent(code);
78 switch (mEvent) {
79 case Event::kStartNamespace:
80 case Event::kEndNamespace:
81 data = mParser->getNamespacePrefix(&len);
82 mStr1.assign(data, len);
83 data = mParser->getNamespaceUri(&len);
84 mStr2.assign(data, len);
85 break;
86
87 case Event::kStartElement:
88 copyAttributes();
89 // fallthrough
90
91 case Event::kEndElement:
92 data = mParser->getElementNamespace(&len);
93 mStr1.assign(data, len);
94 data = mParser->getElementName(&len);
95 mStr2.assign(data, len);
96 break;
97
98 case Event::kText:
99 data = mParser->getText(&len);
100 mStr1.assign(data, len);
101 break;
102
103 default:
104 break;
105 }
106 return mEvent;
107}
108
109XmlPullParser::Event BinaryXmlPullParser::getEvent() const {
110 if (mHasComment) {
111 return XmlPullParser::Event::kComment;
112 }
113 return mEvent;
114}
115
116const std::string& BinaryXmlPullParser::getLastError() const {
117 return sEmpty8;
118}
119
120const std::u16string& BinaryXmlPullParser::getComment() const {
121 if (mHasComment) {
122 return mStr1;
123 }
124 return sEmpty;
125}
126
127size_t BinaryXmlPullParser::getLineNumber() const {
128 return mParser->getLineNumber();
129}
130
131size_t BinaryXmlPullParser::getDepth() const {
132 return mDepth;
133}
134
135const std::u16string& BinaryXmlPullParser::getText() const {
136 if (!mHasComment && mEvent == XmlPullParser::Event::kText) {
137 return mStr1;
138 }
139 return sEmpty;
140}
141
142const std::u16string& BinaryXmlPullParser::getNamespacePrefix() const {
143 if (!mHasComment && (mEvent == XmlPullParser::Event::kStartNamespace ||
144 mEvent == XmlPullParser::Event::kEndNamespace)) {
145 return mStr1;
146 }
147 return sEmpty;
148}
149
150const std::u16string& BinaryXmlPullParser::getNamespaceUri() const {
151 if (!mHasComment && (mEvent == XmlPullParser::Event::kStartNamespace ||
152 mEvent == XmlPullParser::Event::kEndNamespace)) {
153 return mStr2;
154 }
155 return sEmpty;
156}
157
158const std::u16string& BinaryXmlPullParser::getElementNamespace() const {
159 if (!mHasComment && (mEvent == XmlPullParser::Event::kStartElement ||
160 mEvent == XmlPullParser::Event::kEndElement)) {
161 return mStr1;
162 }
163 return sEmpty;
164}
165
166const std::u16string& BinaryXmlPullParser::getElementName() const {
167 if (!mHasComment && (mEvent == XmlPullParser::Event::kStartElement ||
168 mEvent == XmlPullParser::Event::kEndElement)) {
169 return mStr2;
170 }
171 return sEmpty;
172}
173
174size_t BinaryXmlPullParser::getAttributeCount() const {
175 return mAttributes.size();
176}
177
178XmlPullParser::const_iterator BinaryXmlPullParser::beginAttributes() const {
179 return mAttributes.begin();
180}
181
182XmlPullParser::const_iterator BinaryXmlPullParser::endAttributes() const {
183 return mAttributes.end();
184}
185
186void BinaryXmlPullParser::copyAttributes() {
187 const size_t attrCount = mParser->getAttributeCount();
188 if (attrCount > 0) {
189 mAttributes.reserve(attrCount);
190 for (size_t i = 0; i < attrCount; i++) {
191 XmlPullParser::Attribute attr;
192 size_t len;
193 const char16_t* str = mParser->getAttributeNamespace(i, &len);
194 attr.namespaceUri.assign(str, len);
195 str = mParser->getAttributeName(i, &len);
196 attr.name.assign(str, len);
197 str = mParser->getAttributeStringValue(i, &len);
198 attr.value.assign(str, len);
199 mAttributes.push_back(std::move(attr));
200 }
201 }
202}
203
204} // namespace aapt