XmlDom.cpp revision d3ffa844f5a07756009f019e13806e253d1bb119
175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/*
275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Copyright (C) 2015 The Android Open Source Project
375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski *
475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * you may not use this file except in compliance with the License.
675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * You may obtain a copy of the License at
775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski *
875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski *
1075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Unless required by applicable law or agreed to in writing, software
1175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
1275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * See the License for the specific language governing permissions and
1475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * limitations under the License.
1575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
1675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
1775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include "XmlDom.h"
1875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
19467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include <expat.h>
20ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
2175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <memory>
2275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <stack>
2375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <string>
2475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <tuple>
2575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
26ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "android-base/logging.h"
27ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
28d0f492db038c6210c1138865d816bfb134376538Adam Lesinski#include "ResourceUtils.h"
29ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "XmlPullParser.h"
30ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "util/Util.h"
31ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
32efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinskiusing ::aapt::io::InputStream;
33efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinskiusing ::android::StringPiece;
34efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinskiusing ::android::StringPiece16;
35d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski
3675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace aapt {
3775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace xml {
3875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
3975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskiconstexpr char kXmlNamespaceSep = 1;
4075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
4175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistruct Stack {
426b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::unique_ptr<xml::Element> root;
436b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::stack<xml::Element*> node_stack;
446b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::unique_ptr<xml::Element> pending_element;
45ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string pending_comment;
46ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  std::unique_ptr<xml::Text> last_text_node;
4775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski};
4875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
496b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski// Extracts the namespace and name of an expanded element or attribute name.
506b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistatic void SplitName(const char* name, std::string* out_ns, std::string* out_name) {
51ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const char* p = name;
52ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  while (*p != 0 && *p != kXmlNamespaceSep) {
53ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    p++;
54ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
55ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
56ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (*p == 0) {
57ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    out_ns->clear();
58d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski    out_name->assign(name);
59ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  } else {
60d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski    out_ns->assign(name, (p - name));
61d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski    out_name->assign(p + 1);
62ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
6375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
6475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
65ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinskistatic void FinishPendingText(Stack* stack) {
66ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  if (stack->last_text_node != nullptr) {
6748448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski    if (!stack->last_text_node->text.empty()) {
686b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski      CHECK(!stack->node_stack.empty());
69ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski      stack->node_stack.top()->AppendChild(std::move(stack->last_text_node));
70ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski    } else {
71ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski      // Drop an empty text node.
72ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski    }
7348448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski    stack->last_text_node = nullptr;
74ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  }
75ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski}
76ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski
776b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistatic void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix, const char* uri) {
78ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
80ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  FinishPendingText(stack);
8175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
826b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  NamespaceDecl decl;
836b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  decl.line_number = XML_GetCurrentLineNumber(parser);
846b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  decl.column_number = XML_GetCurrentColumnNumber(parser);
856b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  decl.prefix = prefix ? prefix : "";
866b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  decl.uri = uri ? uri : "";
8775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
886b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  if (stack->pending_element == nullptr) {
896b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    stack->pending_element = util::make_unique<Element>();
90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
916b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  stack->pending_element->namespace_decls.push_back(std::move(decl));
9275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
9375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
946b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistatic void XMLCALL EndNamespaceHandler(void* user_data, const char* /*prefix*/) {
95ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
96ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
97ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  FinishPendingText(stack);
9875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
9975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
100ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic bool less_attribute(const Attribute& lhs, const Attribute& rhs) {
101ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return std::tie(lhs.namespace_uri, lhs.name, lhs.value) <
102ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski         std::tie(rhs.namespace_uri, rhs.name, rhs.value);
10375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
10475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
1056b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistatic void XMLCALL StartElementHandler(void* user_data, const char* name, const char** attrs) {
106ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
107ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
108ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  FinishPendingText(stack);
10975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
1106b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::unique_ptr<Element> el;
1116b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  if (stack->pending_element != nullptr) {
1126b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    el = std::move(stack->pending_element);
1136b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  } else {
1146b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    el = util::make_unique<Element>();
1156b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  }
1166b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
1176b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  el->line_number = XML_GetCurrentLineNumber(parser);
1186b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  el->column_number = XML_GetCurrentColumnNumber(parser);
1196b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  el->comment = std::move(stack->pending_comment);
1206b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
121ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  SplitName(name, &el->namespace_uri, &el->name);
12275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
123ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  while (*attrs) {
124ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    Attribute attribute;
125ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    SplitName(*attrs++, &attribute.namespace_uri, &attribute.name);
12648448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski    attribute.value = *attrs++;
1276b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    el->attributes.push_back(std::move(attribute));
128ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
12975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
1306b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  // Sort the attributes.
1316b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::sort(el->attributes.begin(), el->attributes.end(), less_attribute);
1326b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
1336b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  // Add to the stack.
1346b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  Element* this_el = el.get();
1356b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  if (!stack->node_stack.empty()) {
1366b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    stack->node_stack.top()->AppendChild(std::move(el));
1376b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  } else {
1386b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    stack->root = std::move(el);
1396b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  }
1406b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  stack->node_stack.push(this_el);
14175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
14275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
143ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL EndElementHandler(void* user_data, const char* name) {
144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
145ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
146ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  FinishPendingText(stack);
14775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
148ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  CHECK(!stack->node_stack.empty());
149ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // stack->nodeStack.top()->comment = std::move(stack->pendingComment);
150ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  stack->node_stack.pop();
15175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
15275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
153ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinskistatic void XMLCALL CharacterDataHandler(void* user_data, const char* s, int len) {
154ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
155ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
156ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
157ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  const StringPiece str(s, len);
158ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  if (str.empty()) {
159ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return;
160ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
161ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
162ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // See if we can just append the text to a previous text node.
163ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  if (stack->last_text_node != nullptr) {
16448448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski    stack->last_text_node->text.append(str.data(), str.size());
165ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski    return;
166ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
16775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
168ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  stack->last_text_node = util::make_unique<Text>();
169ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  stack->last_text_node->line_number = XML_GetCurrentLineNumber(parser);
170ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  stack->last_text_node->column_number = XML_GetCurrentColumnNumber(parser);
17148448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski  stack->last_text_node->text = str.to_string();
17275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
17375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
174ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL CommentDataHandler(void* user_data, const char* comment) {
175ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
176ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
177ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  FinishPendingText(stack);
17875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
179ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!stack->pending_comment.empty()) {
180ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    stack->pending_comment += '\n';
181ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
182ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  stack->pending_comment += comment;
18375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
18475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
185efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinskistd::unique_ptr<XmlResource> Inflate(InputStream* in, IDiagnostics* diag, const Source& source) {
186ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack stack;
187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
188efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  std::unique_ptr<std::remove_pointer<XML_Parser>::type, decltype(XML_ParserFree)*> parser = {
189efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski      XML_ParserCreateNS(nullptr, kXmlNamespaceSep), XML_ParserFree};
190efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  XML_SetUserData(parser.get(), &stack);
191efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  XML_UseParserAsHandlerArg(parser.get());
192efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  XML_SetElementHandler(parser.get(), StartElementHandler, EndElementHandler);
193efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  XML_SetNamespaceDeclHandler(parser.get(), StartNamespaceHandler, EndNamespaceHandler);
194efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  XML_SetCharacterDataHandler(parser.get(), CharacterDataHandler);
195efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  XML_SetCommentHandler(parser.get(), CommentDataHandler);
196efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski
197efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  const char* buffer = nullptr;
198efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  size_t buffer_size = 0;
199efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  while (in->Next(reinterpret_cast<const void**>(&buffer), &buffer_size)) {
200efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski    if (XML_Parse(parser.get(), buffer, buffer_size, false) == XML_STATUS_ERROR) {
201efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski      diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser.get())))
202efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski                  << XML_ErrorString(XML_GetErrorCode(parser.get())));
203efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski      return {};
2041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
205ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
206ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
207efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  if (in->HadError()) {
208efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski    diag->Error(DiagMessage(source) << in->GetError());
209efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski    return {};
210efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  } else {
211efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski    // Finish off the parsing.
212efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski    if (XML_Parse(parser.get(), nullptr, 0u, true) == XML_STATUS_ERROR) {
213efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski      diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser.get())))
214efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski                  << XML_ErrorString(XML_GetErrorCode(parser.get())));
215efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski      return {};
216efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski    }
217ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
218efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  return util::make_unique<XmlResource>(ResourceFile{{}, {}, source}, StringPool{},
219efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski                                        std::move(stack.root));
22075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
22175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
222d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic void CopyAttributes(Element* el, android::ResXMLParser* parser, StringPool* out_pool) {
223ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const size_t attr_count = parser->getAttributeCount();
224ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (attr_count > 0) {
225ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    el->attributes.reserve(attr_count);
226ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (size_t i = 0; i < attr_count; i++) {
227ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      Attribute attr;
228ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      size_t len;
229ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      const char16_t* str16 = parser->getAttributeNamespace(i, &len);
230ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (str16) {
231ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        attr.namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
232ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
233ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
234ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      str16 = parser->getAttributeName(i, &len);
235ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (str16) {
236ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        attr.name = util::Utf16ToUtf8(StringPiece16(str16, len));
237ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
238ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
2394b8ca8be4d6b0e867f5a421197fa4b5d006fd311Shane Farmer      uint32_t res_id = parser->getAttributeNameResID(i);
2404b8ca8be4d6b0e867f5a421197fa4b5d006fd311Shane Farmer      if (res_id > 0) {
2414b8ca8be4d6b0e867f5a421197fa4b5d006fd311Shane Farmer        attr.compiled_attribute = AaptAttribute(::aapt::Attribute(), {res_id});
2424b8ca8be4d6b0e867f5a421197fa4b5d006fd311Shane Farmer      }
2434b8ca8be4d6b0e867f5a421197fa4b5d006fd311Shane Farmer
244ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      str16 = parser->getAttributeStringValue(i, &len);
245ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (str16) {
246ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        attr.value = util::Utf16ToUtf8(StringPiece16(str16, len));
2474b8ca8be4d6b0e867f5a421197fa4b5d006fd311Shane Farmer      } else {
2484b8ca8be4d6b0e867f5a421197fa4b5d006fd311Shane Farmer        android::Res_value res_value;
2494b8ca8be4d6b0e867f5a421197fa4b5d006fd311Shane Farmer        if (parser->getAttributeValue(i, &res_value) > 0) {
2504b8ca8be4d6b0e867f5a421197fa4b5d006fd311Shane Farmer          attr.compiled_value = ResourceUtils::ParseBinaryResValue(
2514b8ca8be4d6b0e867f5a421197fa4b5d006fd311Shane Farmer              ResourceType::kAnim, {}, parser->getStrings(), res_value, out_pool);
2524b8ca8be4d6b0e867f5a421197fa4b5d006fd311Shane Farmer        }
253ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
254d0f492db038c6210c1138865d816bfb134376538Adam Lesinski
255d0f492db038c6210c1138865d816bfb134376538Adam Lesinski
256ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      el->attributes.push_back(std::move(attr));
25775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
258ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
25975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
26075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
261d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistd::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len, IDiagnostics* diag,
262d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                     const Source& source) {
263ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // We import the android namespace because on Windows NO_ERROR is a macro, not
2646b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  // an enum, which causes errors when qualifying it with android::
265ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  using namespace android;
266803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski
267d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  StringPool string_pool;
2686b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::unique_ptr<Element> root;
2696b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::stack<Element*> node_stack;
2706b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::unique_ptr<Element> pending_element;
27175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
272ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ResXMLTree tree;
273ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (tree.setTo(data, data_len) != NO_ERROR) {
274ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return {};
275ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
276ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
277ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ResXMLParser::event_code_t code;
2786b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT && code != ResXMLParser::END_DOCUMENT) {
279ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<Node> new_node;
280ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    switch (code) {
281ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::START_NAMESPACE: {
2826b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        NamespaceDecl decl;
2831ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski        decl.line_number = tree.getLineNumber();
2841ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski
285ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        size_t len;
286ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const char16_t* str16 = tree.getNamespacePrefix(&len);
287ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
2886b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          decl.prefix = util::Utf16ToUtf8(StringPiece16(str16, len));
289ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
290ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
291ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        str16 = tree.getNamespaceUri(&len);
292ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
2936b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          decl.uri = util::Utf16ToUtf8(StringPiece16(str16, len));
2946b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        }
2956b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
2966b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        if (pending_element == nullptr) {
2976b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          pending_element = util::make_unique<Element>();
298ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
2991ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski        pending_element->namespace_decls.push_back(std::move(decl));
300ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
301ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
302ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
303ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::START_TAG: {
3046b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        std::unique_ptr<Element> el;
3056b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        if (pending_element != nullptr) {
3066b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          el = std::move(pending_element);
3076b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        } else {
3086b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          el = util::make_unique<Element>();
3096b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        }
3101ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski        el->line_number = tree.getLineNumber();
3116b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
312ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        size_t len;
313ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const char16_t* str16 = tree.getElementNamespace(&len);
314ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
3156b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          el->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
316ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
31775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
318ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        str16 = tree.getElementName(&len);
319ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
3206b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          el->name = util::Utf16ToUtf8(StringPiece16(str16, len));
32175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
32275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
3236b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        Element* this_el = el.get();
3246b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        CopyAttributes(el.get(), &tree, &string_pool);
325ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
3266b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        if (!node_stack.empty()) {
3276b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          node_stack.top()->AppendChild(std::move(el));
3286b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        } else {
3296b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          root = std::move(el);
3306b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        }
3316b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        node_stack.push(this_el);
332ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
333ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
334ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
335ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::TEXT: {
3366b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        std::unique_ptr<Text> text = util::make_unique<Text>();
3376b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        text->line_number = tree.getLineNumber();
338ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        size_t len;
339ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const char16_t* str16 = tree.getText(&len);
340ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
3416b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          text->text = util::Utf16ToUtf8(StringPiece16(str16, len));
34275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
3436b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        CHECK(!node_stack.empty());
3446b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        node_stack.top()->AppendChild(std::move(text));
345ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
346ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
347ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
348ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::END_NAMESPACE:
3496b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        break;
3506b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
351ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::END_TAG:
352ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        CHECK(!node_stack.empty());
353ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        node_stack.pop();
354ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
355ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
356ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      default:
357ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        LOG(FATAL) << "unhandled XML chunk type";
358ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
35975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
360ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
361ea134e08d70d156bdd17714d5f9ab9c44c91d4faAdam Lesinski  return util::make_unique<XmlResource>(ResourceFile{}, std::move(string_pool), std::move(root));
3625eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
3635eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
364ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* FindRootElement(Node* node) {
3656b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  if (node == nullptr) {
366ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return nullptr;
367ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
368ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
3696b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  while (node->parent != nullptr) {
3706b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    node = node->parent;
371ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
3726b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  return NodeCast<Element>(node);
373ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski}
374ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski
3756b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Element::AppendChild(std::unique_ptr<Node> child) {
376ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  child->parent = this;
377ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  children.push_back(std::move(child));
37875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
37975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
3806b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Element::InsertChild(size_t index, std::unique_ptr<Node> child) {
381e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski  child->parent = this;
382e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski  children.insert(children.begin() + index, std::move(child));
383e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski}
384e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski
3856b372991296c9f2bd6f8f8847dcd23d50970d06dAdam LesinskiAttribute* Element::FindAttribute(const StringPiece& ns, const StringPiece& name) {
386ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (auto& attr : attributes) {
387ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (ns == attr.namespace_uri && name == attr.name) {
388ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return &attr;
38975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
390ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
391ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return nullptr;
39275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
39375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
394c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskiconst Attribute* Element::FindAttribute(const StringPiece& ns, const StringPiece& name) const {
395c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  for (const auto& attr : attributes) {
396c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    if (ns == attr.namespace_uri && name == attr.name) {
397c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      return &attr;
398c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    }
399c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  }
400c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  return nullptr;
401c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski}
402c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
403ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* Element::FindChild(const StringPiece& ns, const StringPiece& name) {
404ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return FindChildWithAttribute(ns, name, {}, {}, {});
40575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
40675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
4076b372991296c9f2bd6f8f8847dcd23d50970d06dAdam LesinskiElement* Element::FindChildWithAttribute(const StringPiece& ns, const StringPiece& name,
4086b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski                                         const StringPiece& attr_ns, const StringPiece& attr_name,
409ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                         const StringPiece& attr_value) {
4106b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  for (auto& child : children) {
4116b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    if (Element* el = NodeCast<Element>(child.get())) {
412ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (ns == el->namespace_uri && name == el->name) {
413ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (attr_ns.empty() && attr_name.empty()) {
414ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          return el;
41575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
41675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
417ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        Attribute* attr = el->FindAttribute(attr_ns, attr_name);
418ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (attr && attr_value == attr->value) {
419ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          return el;
42075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
421ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
42275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
423ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
424ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return nullptr;
42575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
42675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
427ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::vector<Element*> Element::GetChildElements() {
428ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<Element*> elements;
429ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (auto& child_node : children) {
4306b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    if (Element* child = NodeCast<Element>(child_node.get())) {
4316b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski      elements.push_back(child);
4325eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski    }
433ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
434ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return elements;
4355eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
4365eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
4376b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistd::unique_ptr<Node> Element::Clone(const ElementCloneFunc& el_cloner) const {
438ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  auto el = util::make_unique<Element>();
4396b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  el->namespace_decls = namespace_decls;
440ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->comment = comment;
441ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->line_number = line_number;
442ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->column_number = column_number;
443ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->name = name;
444ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->namespace_uri = namespace_uri;
445ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->attributes.reserve(attributes.size());
446c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  el_cloner(*this, el.get());
447ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->children.reserve(children.size());
448ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const std::unique_ptr<xml::Node>& child : children) {
449c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    el->AppendChild(child->Clone(el_cloner));
450ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
451ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return std::move(el);
4525eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
4535eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
4546b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistd::unique_ptr<Element> Element::CloneElement(const ElementCloneFunc& el_cloner) const {
4556b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  return std::unique_ptr<Element>(static_cast<Element*>(Clone(el_cloner).release()));
4566b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski}
4576b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
4586b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Element::Accept(Visitor* visitor) {
4596b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  visitor->BeforeVisitElement(this);
4606b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  visitor->Visit(this);
4616b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  visitor->AfterVisitElement(this);
4626b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski}
4636b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
464d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinskivoid Element::Accept(ConstVisitor* visitor) const {
465d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski  visitor->BeforeVisitElement(this);
466d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski  visitor->Visit(this);
467d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski  visitor->AfterVisitElement(this);
468d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski}
469d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski
4706b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistd::unique_ptr<Node> Text::Clone(const ElementCloneFunc&) const {
471ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  auto t = util::make_unique<Text>();
472ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->comment = comment;
473ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->line_number = line_number;
474ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->column_number = column_number;
475ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->text = text;
476ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return std::move(t);
477ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}
478467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
4796b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Text::Accept(Visitor* visitor) {
4806b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  visitor->Visit(this);
4816b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski}
482ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
483d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinskivoid Text::Accept(ConstVisitor* visitor) const {
484d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski  visitor->Visit(this);
485d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski}
486d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski
4876b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid PackageAwareVisitor::BeforeVisitElement(Element* el) {
4886b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::vector<PackageDecl> decls;
4896b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  for (const NamespaceDecl& decl : el->namespace_decls) {
4906b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    if (Maybe<ExtractedPackage> maybe_package = ExtractPackageFromNamespace(decl.uri)) {
4916b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski      decls.push_back(PackageDecl{decl.prefix, std::move(maybe_package.value())});
4926b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    }
493ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
4946b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  package_decls_.push_back(std::move(decls));
4956b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski}
4966b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
4976b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid PackageAwareVisitor::AfterVisitElement(Element* el) {
4986b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  package_decls_.pop_back();
499467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski}
500467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
5011ef0fa9d7242b1926543bc49e35905d1be02a781Adam LesinskiMaybe<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias(const StringPiece& alias) const {
502ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (alias.empty()) {
5031ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski    return ExtractedPackage{{}, false /*private*/};
504ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
505ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
506ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const auto rend = package_decls_.rend();
507ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) {
5086b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    const std::vector<PackageDecl>& decls = *iter;
5096b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    const auto rend2 = decls.rend();
5106b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    for (auto iter2 = decls.rbegin(); iter2 != rend2; ++iter2) {
5116b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski      const PackageDecl& decl = *iter2;
5126b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski      if (alias == decl.prefix) {
5136b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        if (decl.package.package.empty()) {
5141ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski          return ExtractedPackage{{}, decl.package.private_namespace};
5156b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        }
5166b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        return decl.package;
517ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
518ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    }
519ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
520ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return {};
521467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski}
522467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
523ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}  // namespace xml
524ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}  // namespace aapt
525