1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker *
4*d57664e9SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker *
8*d57664e9SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker *
10*d57664e9SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker */
16*d57664e9SAndroid Build Coastguard Worker
17*d57664e9SAndroid Build Coastguard Worker #include "xml/XmlPullParser.h"
18*d57664e9SAndroid Build Coastguard Worker
19*d57664e9SAndroid Build Coastguard Worker #include <algorithm>
20*d57664e9SAndroid Build Coastguard Worker #include <string>
21*d57664e9SAndroid Build Coastguard Worker #include <tuple>
22*d57664e9SAndroid Build Coastguard Worker
23*d57664e9SAndroid Build Coastguard Worker #include "util/Util.h"
24*d57664e9SAndroid Build Coastguard Worker #include "xml/XmlUtil.h"
25*d57664e9SAndroid Build Coastguard Worker
26*d57664e9SAndroid Build Coastguard Worker using ::android::InputStream;
27*d57664e9SAndroid Build Coastguard Worker using ::android::StringPiece;
28*d57664e9SAndroid Build Coastguard Worker
29*d57664e9SAndroid Build Coastguard Worker namespace aapt {
30*d57664e9SAndroid Build Coastguard Worker namespace xml {
31*d57664e9SAndroid Build Coastguard Worker
32*d57664e9SAndroid Build Coastguard Worker constexpr char kXmlNamespaceSep = 1;
33*d57664e9SAndroid Build Coastguard Worker
XmlPullParser(InputStream * in)34*d57664e9SAndroid Build Coastguard Worker XmlPullParser::XmlPullParser(InputStream* in) : in_(in), empty_(), depth_(0) {
35*d57664e9SAndroid Build Coastguard Worker parser_ = XML_ParserCreateNS(nullptr, kXmlNamespaceSep);
36*d57664e9SAndroid Build Coastguard Worker XML_SetUserData(parser_, this);
37*d57664e9SAndroid Build Coastguard Worker XML_SetElementHandler(parser_, StartElementHandler, EndElementHandler);
38*d57664e9SAndroid Build Coastguard Worker XML_SetNamespaceDeclHandler(parser_, StartNamespaceHandler,
39*d57664e9SAndroid Build Coastguard Worker EndNamespaceHandler);
40*d57664e9SAndroid Build Coastguard Worker XML_SetCharacterDataHandler(parser_, CharacterDataHandler);
41*d57664e9SAndroid Build Coastguard Worker XML_SetCommentHandler(parser_, CommentDataHandler);
42*d57664e9SAndroid Build Coastguard Worker XML_SetCdataSectionHandler(parser_, StartCdataSectionHandler, EndCdataSectionHandler);
43*d57664e9SAndroid Build Coastguard Worker event_queue_.push(EventData{Event::kStartDocument, 0, depth_++});
44*d57664e9SAndroid Build Coastguard Worker }
45*d57664e9SAndroid Build Coastguard Worker
~XmlPullParser()46*d57664e9SAndroid Build Coastguard Worker XmlPullParser::~XmlPullParser() {
47*d57664e9SAndroid Build Coastguard Worker XML_ParserFree(parser_);
48*d57664e9SAndroid Build Coastguard Worker }
49*d57664e9SAndroid Build Coastguard Worker
Next()50*d57664e9SAndroid Build Coastguard Worker XmlPullParser::Event XmlPullParser::Next() {
51*d57664e9SAndroid Build Coastguard Worker const Event currentEvent = event();
52*d57664e9SAndroid Build Coastguard Worker if (currentEvent == Event::kBadDocument || currentEvent == Event::kEndDocument) {
53*d57664e9SAndroid Build Coastguard Worker return currentEvent;
54*d57664e9SAndroid Build Coastguard Worker }
55*d57664e9SAndroid Build Coastguard Worker
56*d57664e9SAndroid Build Coastguard Worker event_queue_.pop();
57*d57664e9SAndroid Build Coastguard Worker while (event_queue_.empty()) {
58*d57664e9SAndroid Build Coastguard Worker const char* buffer = nullptr;
59*d57664e9SAndroid Build Coastguard Worker size_t buffer_size = 0;
60*d57664e9SAndroid Build Coastguard Worker bool done = false;
61*d57664e9SAndroid Build Coastguard Worker if (!in_->Next(reinterpret_cast<const void**>(&buffer), &buffer_size)) {
62*d57664e9SAndroid Build Coastguard Worker if (in_->HadError()) {
63*d57664e9SAndroid Build Coastguard Worker error_ = in_->GetError();
64*d57664e9SAndroid Build Coastguard Worker event_queue_.push(EventData{Event::kBadDocument});
65*d57664e9SAndroid Build Coastguard Worker break;
66*d57664e9SAndroid Build Coastguard Worker }
67*d57664e9SAndroid Build Coastguard Worker
68*d57664e9SAndroid Build Coastguard Worker done = true;
69*d57664e9SAndroid Build Coastguard Worker }
70*d57664e9SAndroid Build Coastguard Worker
71*d57664e9SAndroid Build Coastguard Worker if (XML_Parse(parser_, buffer, buffer_size, done) == XML_STATUS_ERROR) {
72*d57664e9SAndroid Build Coastguard Worker error_ = XML_ErrorString(XML_GetErrorCode(parser_));
73*d57664e9SAndroid Build Coastguard Worker event_queue_.push(EventData{Event::kBadDocument});
74*d57664e9SAndroid Build Coastguard Worker break;
75*d57664e9SAndroid Build Coastguard Worker }
76*d57664e9SAndroid Build Coastguard Worker
77*d57664e9SAndroid Build Coastguard Worker if (done) {
78*d57664e9SAndroid Build Coastguard Worker event_queue_.push(EventData{Event::kEndDocument, 0, 0});
79*d57664e9SAndroid Build Coastguard Worker }
80*d57664e9SAndroid Build Coastguard Worker }
81*d57664e9SAndroid Build Coastguard Worker
82*d57664e9SAndroid Build Coastguard Worker Event next_event = event();
83*d57664e9SAndroid Build Coastguard Worker
84*d57664e9SAndroid Build Coastguard Worker // Record namespace prefixes and package names so that we can do our own
85*d57664e9SAndroid Build Coastguard Worker // handling of references that use namespace aliases.
86*d57664e9SAndroid Build Coastguard Worker if (next_event == Event::kStartNamespace ||
87*d57664e9SAndroid Build Coastguard Worker next_event == Event::kEndNamespace) {
88*d57664e9SAndroid Build Coastguard Worker std::optional<ExtractedPackage> result = ExtractPackageFromNamespace(namespace_uri());
89*d57664e9SAndroid Build Coastguard Worker if (next_event == Event::kStartNamespace) {
90*d57664e9SAndroid Build Coastguard Worker if (result) {
91*d57664e9SAndroid Build Coastguard Worker package_aliases_.emplace_back(
92*d57664e9SAndroid Build Coastguard Worker PackageDecl{namespace_prefix(), std::move(result.value())});
93*d57664e9SAndroid Build Coastguard Worker }
94*d57664e9SAndroid Build Coastguard Worker } else {
95*d57664e9SAndroid Build Coastguard Worker if (result) {
96*d57664e9SAndroid Build Coastguard Worker package_aliases_.pop_back();
97*d57664e9SAndroid Build Coastguard Worker }
98*d57664e9SAndroid Build Coastguard Worker }
99*d57664e9SAndroid Build Coastguard Worker }
100*d57664e9SAndroid Build Coastguard Worker
101*d57664e9SAndroid Build Coastguard Worker return next_event;
102*d57664e9SAndroid Build Coastguard Worker }
103*d57664e9SAndroid Build Coastguard Worker
event() const104*d57664e9SAndroid Build Coastguard Worker XmlPullParser::Event XmlPullParser::event() const {
105*d57664e9SAndroid Build Coastguard Worker return event_queue_.front().event;
106*d57664e9SAndroid Build Coastguard Worker }
107*d57664e9SAndroid Build Coastguard Worker
error() const108*d57664e9SAndroid Build Coastguard Worker const std::string& XmlPullParser::error() const { return error_; }
109*d57664e9SAndroid Build Coastguard Worker
comment() const110*d57664e9SAndroid Build Coastguard Worker const std::string& XmlPullParser::comment() const {
111*d57664e9SAndroid Build Coastguard Worker return event_queue_.front().data1;
112*d57664e9SAndroid Build Coastguard Worker }
113*d57664e9SAndroid Build Coastguard Worker
line_number() const114*d57664e9SAndroid Build Coastguard Worker size_t XmlPullParser::line_number() const {
115*d57664e9SAndroid Build Coastguard Worker return event_queue_.front().line_number;
116*d57664e9SAndroid Build Coastguard Worker }
117*d57664e9SAndroid Build Coastguard Worker
depth() const118*d57664e9SAndroid Build Coastguard Worker size_t XmlPullParser::depth() const { return event_queue_.front().depth; }
119*d57664e9SAndroid Build Coastguard Worker
text() const120*d57664e9SAndroid Build Coastguard Worker const std::string& XmlPullParser::text() const {
121*d57664e9SAndroid Build Coastguard Worker if (event() != Event::kText) {
122*d57664e9SAndroid Build Coastguard Worker return empty_;
123*d57664e9SAndroid Build Coastguard Worker }
124*d57664e9SAndroid Build Coastguard Worker return event_queue_.front().data1;
125*d57664e9SAndroid Build Coastguard Worker }
126*d57664e9SAndroid Build Coastguard Worker
namespace_prefix() const127*d57664e9SAndroid Build Coastguard Worker const std::string& XmlPullParser::namespace_prefix() const {
128*d57664e9SAndroid Build Coastguard Worker const Event current_event = event();
129*d57664e9SAndroid Build Coastguard Worker if (current_event != Event::kStartNamespace &&
130*d57664e9SAndroid Build Coastguard Worker current_event != Event::kEndNamespace) {
131*d57664e9SAndroid Build Coastguard Worker return empty_;
132*d57664e9SAndroid Build Coastguard Worker }
133*d57664e9SAndroid Build Coastguard Worker return event_queue_.front().data1;
134*d57664e9SAndroid Build Coastguard Worker }
135*d57664e9SAndroid Build Coastguard Worker
namespace_uri() const136*d57664e9SAndroid Build Coastguard Worker const std::string& XmlPullParser::namespace_uri() const {
137*d57664e9SAndroid Build Coastguard Worker const Event current_event = event();
138*d57664e9SAndroid Build Coastguard Worker if (current_event != Event::kStartNamespace &&
139*d57664e9SAndroid Build Coastguard Worker current_event != Event::kEndNamespace) {
140*d57664e9SAndroid Build Coastguard Worker return empty_;
141*d57664e9SAndroid Build Coastguard Worker }
142*d57664e9SAndroid Build Coastguard Worker return event_queue_.front().data2;
143*d57664e9SAndroid Build Coastguard Worker }
144*d57664e9SAndroid Build Coastguard Worker
TransformPackageAlias(StringPiece alias) const145*d57664e9SAndroid Build Coastguard Worker std::optional<ExtractedPackage> XmlPullParser::TransformPackageAlias(StringPiece alias) const {
146*d57664e9SAndroid Build Coastguard Worker if (alias.empty()) {
147*d57664e9SAndroid Build Coastguard Worker return ExtractedPackage{{}, false /*private*/};
148*d57664e9SAndroid Build Coastguard Worker }
149*d57664e9SAndroid Build Coastguard Worker
150*d57664e9SAndroid Build Coastguard Worker const auto end_iter = package_aliases_.rend();
151*d57664e9SAndroid Build Coastguard Worker for (auto iter = package_aliases_.rbegin(); iter != end_iter; ++iter) {
152*d57664e9SAndroid Build Coastguard Worker if (alias == iter->prefix) {
153*d57664e9SAndroid Build Coastguard Worker if (iter->package.package.empty()) {
154*d57664e9SAndroid Build Coastguard Worker return ExtractedPackage{{}, iter->package.private_namespace};
155*d57664e9SAndroid Build Coastguard Worker }
156*d57664e9SAndroid Build Coastguard Worker return iter->package;
157*d57664e9SAndroid Build Coastguard Worker }
158*d57664e9SAndroid Build Coastguard Worker }
159*d57664e9SAndroid Build Coastguard Worker return {};
160*d57664e9SAndroid Build Coastguard Worker }
161*d57664e9SAndroid Build Coastguard Worker
element_namespace() const162*d57664e9SAndroid Build Coastguard Worker const std::string& XmlPullParser::element_namespace() const {
163*d57664e9SAndroid Build Coastguard Worker const Event current_event = event();
164*d57664e9SAndroid Build Coastguard Worker if (current_event != Event::kStartElement &&
165*d57664e9SAndroid Build Coastguard Worker current_event != Event::kEndElement) {
166*d57664e9SAndroid Build Coastguard Worker return empty_;
167*d57664e9SAndroid Build Coastguard Worker }
168*d57664e9SAndroid Build Coastguard Worker return event_queue_.front().data1;
169*d57664e9SAndroid Build Coastguard Worker }
170*d57664e9SAndroid Build Coastguard Worker
element_name() const171*d57664e9SAndroid Build Coastguard Worker const std::string& XmlPullParser::element_name() const {
172*d57664e9SAndroid Build Coastguard Worker const Event current_event = event();
173*d57664e9SAndroid Build Coastguard Worker if (current_event != Event::kStartElement &&
174*d57664e9SAndroid Build Coastguard Worker current_event != Event::kEndElement) {
175*d57664e9SAndroid Build Coastguard Worker return empty_;
176*d57664e9SAndroid Build Coastguard Worker }
177*d57664e9SAndroid Build Coastguard Worker return event_queue_.front().data2;
178*d57664e9SAndroid Build Coastguard Worker }
179*d57664e9SAndroid Build Coastguard Worker
package_decls() const180*d57664e9SAndroid Build Coastguard Worker const std::vector<XmlPullParser::PackageDecl>& XmlPullParser::package_decls() const {
181*d57664e9SAndroid Build Coastguard Worker return package_aliases_;
182*d57664e9SAndroid Build Coastguard Worker }
183*d57664e9SAndroid Build Coastguard Worker
begin_attributes() const184*d57664e9SAndroid Build Coastguard Worker XmlPullParser::const_iterator XmlPullParser::begin_attributes() const {
185*d57664e9SAndroid Build Coastguard Worker return event_queue_.front().attributes.begin();
186*d57664e9SAndroid Build Coastguard Worker }
187*d57664e9SAndroid Build Coastguard Worker
end_attributes() const188*d57664e9SAndroid Build Coastguard Worker XmlPullParser::const_iterator XmlPullParser::end_attributes() const {
189*d57664e9SAndroid Build Coastguard Worker return event_queue_.front().attributes.end();
190*d57664e9SAndroid Build Coastguard Worker }
191*d57664e9SAndroid Build Coastguard Worker
attribute_count() const192*d57664e9SAndroid Build Coastguard Worker size_t XmlPullParser::attribute_count() const {
193*d57664e9SAndroid Build Coastguard Worker if (event() != Event::kStartElement) {
194*d57664e9SAndroid Build Coastguard Worker return 0;
195*d57664e9SAndroid Build Coastguard Worker }
196*d57664e9SAndroid Build Coastguard Worker return event_queue_.front().attributes.size();
197*d57664e9SAndroid Build Coastguard Worker }
198*d57664e9SAndroid Build Coastguard Worker
199*d57664e9SAndroid Build Coastguard Worker /**
200*d57664e9SAndroid Build Coastguard Worker * Extracts the namespace and name of an expanded element or attribute name.
201*d57664e9SAndroid Build Coastguard Worker */
SplitName(const char * name,std::string * out_ns,std::string * out_name)202*d57664e9SAndroid Build Coastguard Worker static void SplitName(const char* name, std::string* out_ns, std::string* out_name) {
203*d57664e9SAndroid Build Coastguard Worker const char* p = name;
204*d57664e9SAndroid Build Coastguard Worker while (*p != 0 && *p != kXmlNamespaceSep) {
205*d57664e9SAndroid Build Coastguard Worker p++;
206*d57664e9SAndroid Build Coastguard Worker }
207*d57664e9SAndroid Build Coastguard Worker
208*d57664e9SAndroid Build Coastguard Worker if (*p == 0) {
209*d57664e9SAndroid Build Coastguard Worker out_ns->clear();
210*d57664e9SAndroid Build Coastguard Worker out_name->assign(name);
211*d57664e9SAndroid Build Coastguard Worker } else {
212*d57664e9SAndroid Build Coastguard Worker out_ns->assign(name, (p - name));
213*d57664e9SAndroid Build Coastguard Worker out_name->assign(p + 1);
214*d57664e9SAndroid Build Coastguard Worker }
215*d57664e9SAndroid Build Coastguard Worker }
216*d57664e9SAndroid Build Coastguard Worker
StartNamespaceHandler(void * user_data,const char * prefix,const char * uri)217*d57664e9SAndroid Build Coastguard Worker void XMLCALL XmlPullParser::StartNamespaceHandler(void* user_data,
218*d57664e9SAndroid Build Coastguard Worker const char* prefix,
219*d57664e9SAndroid Build Coastguard Worker const char* uri) {
220*d57664e9SAndroid Build Coastguard Worker XmlPullParser* parser = reinterpret_cast<XmlPullParser*>(user_data);
221*d57664e9SAndroid Build Coastguard Worker std::string namespace_uri = uri != nullptr ? uri : std::string();
222*d57664e9SAndroid Build Coastguard Worker parser->namespace_uris_.push(namespace_uri);
223*d57664e9SAndroid Build Coastguard Worker parser->event_queue_.push(
224*d57664e9SAndroid Build Coastguard Worker EventData{Event::kStartNamespace,
225*d57664e9SAndroid Build Coastguard Worker XML_GetCurrentLineNumber(parser->parser_), parser->depth_++,
226*d57664e9SAndroid Build Coastguard Worker prefix != nullptr ? prefix : std::string(), namespace_uri});
227*d57664e9SAndroid Build Coastguard Worker }
228*d57664e9SAndroid Build Coastguard Worker
StartElementHandler(void * user_data,const char * name,const char ** attrs)229*d57664e9SAndroid Build Coastguard Worker void XMLCALL XmlPullParser::StartElementHandler(void* user_data,
230*d57664e9SAndroid Build Coastguard Worker const char* name,
231*d57664e9SAndroid Build Coastguard Worker const char** attrs) {
232*d57664e9SAndroid Build Coastguard Worker XmlPullParser* parser = reinterpret_cast<XmlPullParser*>(user_data);
233*d57664e9SAndroid Build Coastguard Worker
234*d57664e9SAndroid Build Coastguard Worker EventData data = {Event::kStartElement,
235*d57664e9SAndroid Build Coastguard Worker XML_GetCurrentLineNumber(parser->parser_),
236*d57664e9SAndroid Build Coastguard Worker parser->depth_++};
237*d57664e9SAndroid Build Coastguard Worker SplitName(name, &data.data1, &data.data2);
238*d57664e9SAndroid Build Coastguard Worker
239*d57664e9SAndroid Build Coastguard Worker while (*attrs) {
240*d57664e9SAndroid Build Coastguard Worker Attribute attribute;
241*d57664e9SAndroid Build Coastguard Worker SplitName(*attrs++, &attribute.namespace_uri, &attribute.name);
242*d57664e9SAndroid Build Coastguard Worker attribute.value = *attrs++;
243*d57664e9SAndroid Build Coastguard Worker
244*d57664e9SAndroid Build Coastguard Worker // Insert in sorted order.
245*d57664e9SAndroid Build Coastguard Worker auto iter = std::lower_bound(data.attributes.begin(), data.attributes.end(),
246*d57664e9SAndroid Build Coastguard Worker attribute);
247*d57664e9SAndroid Build Coastguard Worker data.attributes.insert(iter, std::move(attribute));
248*d57664e9SAndroid Build Coastguard Worker }
249*d57664e9SAndroid Build Coastguard Worker
250*d57664e9SAndroid Build Coastguard Worker // Move the structure into the queue (no copy).
251*d57664e9SAndroid Build Coastguard Worker parser->event_queue_.push(std::move(data));
252*d57664e9SAndroid Build Coastguard Worker }
253*d57664e9SAndroid Build Coastguard Worker
CharacterDataHandler(void * user_data,const char * s,int len)254*d57664e9SAndroid Build Coastguard Worker void XMLCALL XmlPullParser::CharacterDataHandler(void* user_data, const char* s,
255*d57664e9SAndroid Build Coastguard Worker int len) {
256*d57664e9SAndroid Build Coastguard Worker XmlPullParser* parser = reinterpret_cast<XmlPullParser*>(user_data);
257*d57664e9SAndroid Build Coastguard Worker
258*d57664e9SAndroid Build Coastguard Worker parser->event_queue_.push(EventData{Event::kText, XML_GetCurrentLineNumber(parser->parser_),
259*d57664e9SAndroid Build Coastguard Worker parser->depth_, std::string(s, len)});
260*d57664e9SAndroid Build Coastguard Worker }
261*d57664e9SAndroid Build Coastguard Worker
EndElementHandler(void * user_data,const char * name)262*d57664e9SAndroid Build Coastguard Worker void XMLCALL XmlPullParser::EndElementHandler(void* user_data,
263*d57664e9SAndroid Build Coastguard Worker const char* name) {
264*d57664e9SAndroid Build Coastguard Worker XmlPullParser* parser = reinterpret_cast<XmlPullParser*>(user_data);
265*d57664e9SAndroid Build Coastguard Worker
266*d57664e9SAndroid Build Coastguard Worker EventData data = {Event::kEndElement,
267*d57664e9SAndroid Build Coastguard Worker XML_GetCurrentLineNumber(parser->parser_),
268*d57664e9SAndroid Build Coastguard Worker --(parser->depth_)};
269*d57664e9SAndroid Build Coastguard Worker SplitName(name, &data.data1, &data.data2);
270*d57664e9SAndroid Build Coastguard Worker
271*d57664e9SAndroid Build Coastguard Worker // Move the data into the queue (no copy).
272*d57664e9SAndroid Build Coastguard Worker parser->event_queue_.push(std::move(data));
273*d57664e9SAndroid Build Coastguard Worker }
274*d57664e9SAndroid Build Coastguard Worker
EndNamespaceHandler(void * user_data,const char * prefix)275*d57664e9SAndroid Build Coastguard Worker void XMLCALL XmlPullParser::EndNamespaceHandler(void* user_data,
276*d57664e9SAndroid Build Coastguard Worker const char* prefix) {
277*d57664e9SAndroid Build Coastguard Worker XmlPullParser* parser = reinterpret_cast<XmlPullParser*>(user_data);
278*d57664e9SAndroid Build Coastguard Worker
279*d57664e9SAndroid Build Coastguard Worker parser->event_queue_.push(
280*d57664e9SAndroid Build Coastguard Worker EventData{Event::kEndNamespace, XML_GetCurrentLineNumber(parser->parser_),
281*d57664e9SAndroid Build Coastguard Worker --(parser->depth_), prefix != nullptr ? prefix : std::string(),
282*d57664e9SAndroid Build Coastguard Worker parser->namespace_uris_.top()});
283*d57664e9SAndroid Build Coastguard Worker parser->namespace_uris_.pop();
284*d57664e9SAndroid Build Coastguard Worker }
285*d57664e9SAndroid Build Coastguard Worker
CommentDataHandler(void * user_data,const char * comment)286*d57664e9SAndroid Build Coastguard Worker void XMLCALL XmlPullParser::CommentDataHandler(void* user_data,
287*d57664e9SAndroid Build Coastguard Worker const char* comment) {
288*d57664e9SAndroid Build Coastguard Worker XmlPullParser* parser = reinterpret_cast<XmlPullParser*>(user_data);
289*d57664e9SAndroid Build Coastguard Worker
290*d57664e9SAndroid Build Coastguard Worker parser->event_queue_.push(EventData{Event::kComment,
291*d57664e9SAndroid Build Coastguard Worker XML_GetCurrentLineNumber(parser->parser_),
292*d57664e9SAndroid Build Coastguard Worker parser->depth_, comment});
293*d57664e9SAndroid Build Coastguard Worker }
294*d57664e9SAndroid Build Coastguard Worker
StartCdataSectionHandler(void * user_data)295*d57664e9SAndroid Build Coastguard Worker void XMLCALL XmlPullParser::StartCdataSectionHandler(void* user_data) {
296*d57664e9SAndroid Build Coastguard Worker XmlPullParser* parser = reinterpret_cast<XmlPullParser*>(user_data);
297*d57664e9SAndroid Build Coastguard Worker
298*d57664e9SAndroid Build Coastguard Worker parser->event_queue_.push(EventData{Event::kCdataStart,
299*d57664e9SAndroid Build Coastguard Worker XML_GetCurrentLineNumber(parser->parser_),
300*d57664e9SAndroid Build Coastguard Worker parser->depth_ });
301*d57664e9SAndroid Build Coastguard Worker }
302*d57664e9SAndroid Build Coastguard Worker
EndCdataSectionHandler(void * user_data)303*d57664e9SAndroid Build Coastguard Worker void XMLCALL XmlPullParser::EndCdataSectionHandler(void* user_data) {
304*d57664e9SAndroid Build Coastguard Worker XmlPullParser* parser = reinterpret_cast<XmlPullParser*>(user_data);
305*d57664e9SAndroid Build Coastguard Worker
306*d57664e9SAndroid Build Coastguard Worker parser->event_queue_.push(EventData{Event::kCdataEnd,
307*d57664e9SAndroid Build Coastguard Worker XML_GetCurrentLineNumber(parser->parser_),
308*d57664e9SAndroid Build Coastguard Worker parser->depth_ });
309*d57664e9SAndroid Build Coastguard Worker }
310*d57664e9SAndroid Build Coastguard Worker
FindAttribute(const XmlPullParser * parser,StringPiece name)311*d57664e9SAndroid Build Coastguard Worker std::optional<StringPiece> FindAttribute(const XmlPullParser* parser, StringPiece name) {
312*d57664e9SAndroid Build Coastguard Worker return FindAttribute(parser, "", name);
313*d57664e9SAndroid Build Coastguard Worker }
314*d57664e9SAndroid Build Coastguard Worker
FindAttribute(const XmlPullParser * parser,android::StringPiece namespace_uri,android::StringPiece name)315*d57664e9SAndroid Build Coastguard Worker std::optional<android::StringPiece> FindAttribute(const XmlPullParser* parser,
316*d57664e9SAndroid Build Coastguard Worker android::StringPiece namespace_uri,
317*d57664e9SAndroid Build Coastguard Worker android::StringPiece name) {
318*d57664e9SAndroid Build Coastguard Worker auto iter = parser->FindAttribute(namespace_uri, name);
319*d57664e9SAndroid Build Coastguard Worker
320*d57664e9SAndroid Build Coastguard Worker if (iter != parser->end_attributes()) {
321*d57664e9SAndroid Build Coastguard Worker return StringPiece(util::TrimWhitespace(iter->value));
322*d57664e9SAndroid Build Coastguard Worker }
323*d57664e9SAndroid Build Coastguard Worker return {};
324*d57664e9SAndroid Build Coastguard Worker }
325*d57664e9SAndroid Build Coastguard Worker
FindNonEmptyAttribute(const XmlPullParser * parser,StringPiece name)326*d57664e9SAndroid Build Coastguard Worker std::optional<StringPiece> FindNonEmptyAttribute(const XmlPullParser* parser, StringPiece name) {
327*d57664e9SAndroid Build Coastguard Worker auto iter = parser->FindAttribute("", name);
328*d57664e9SAndroid Build Coastguard Worker if (iter != parser->end_attributes()) {
329*d57664e9SAndroid Build Coastguard Worker StringPiece trimmed = util::TrimWhitespace(iter->value);
330*d57664e9SAndroid Build Coastguard Worker if (!trimmed.empty()) {
331*d57664e9SAndroid Build Coastguard Worker return trimmed;
332*d57664e9SAndroid Build Coastguard Worker }
333*d57664e9SAndroid Build Coastguard Worker }
334*d57664e9SAndroid Build Coastguard Worker return {};
335*d57664e9SAndroid Build Coastguard Worker }
336*d57664e9SAndroid Build Coastguard Worker
FindAttribute(android::StringPiece namespace_uri,android::StringPiece name) const337*d57664e9SAndroid Build Coastguard Worker XmlPullParser::const_iterator XmlPullParser::FindAttribute(android::StringPiece namespace_uri,
338*d57664e9SAndroid Build Coastguard Worker android::StringPiece name) const {
339*d57664e9SAndroid Build Coastguard Worker const auto end_iter = end_attributes();
340*d57664e9SAndroid Build Coastguard Worker const auto iter = std::lower_bound(begin_attributes(), end_iter, std::tuple(namespace_uri, name),
341*d57664e9SAndroid Build Coastguard Worker [](const Attribute& attr, const auto& rhs) {
342*d57664e9SAndroid Build Coastguard Worker return std::tie(attr.namespace_uri, attr.name) < rhs;
343*d57664e9SAndroid Build Coastguard Worker });
344*d57664e9SAndroid Build Coastguard Worker if (iter != end_iter && namespace_uri == iter->namespace_uri && name == iter->name) {
345*d57664e9SAndroid Build Coastguard Worker return iter;
346*d57664e9SAndroid Build Coastguard Worker }
347*d57664e9SAndroid Build Coastguard Worker return end_iter;
348*d57664e9SAndroid Build Coastguard Worker }
349*d57664e9SAndroid Build Coastguard Worker
350*d57664e9SAndroid Build Coastguard Worker } // namespace xml
351*d57664e9SAndroid Build Coastguard Worker } // namespace aapt
352