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  }
218004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  return util::make_unique<XmlResource>(ResourceFile{{}, {}, ResourceFile::Type::kUnknown, source},
219004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski                                        StringPool{}, 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));
247ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
248d0f492db038c6210c1138865d816bfb134376538Adam Lesinski
249bbf429795d0558797e7ac8d1024fa5c16552e96cAdam Lesinski      android::Res_value res_value;
250bbf429795d0558797e7ac8d1024fa5c16552e96cAdam Lesinski      if (parser->getAttributeValue(i, &res_value) > 0) {
251e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski        // Only compile the value if it is not a string, or it is a string that differs from
252e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski        // the raw attribute value.
253e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski        int32_t raw_value_idx = parser->getAttributeValueStringID(i);
254e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski        if (res_value.dataType != android::Res_value::TYPE_STRING || raw_value_idx < 0 ||
255e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski            static_cast<uint32_t>(raw_value_idx) != res_value.data) {
256e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski          attr.compiled_value = ResourceUtils::ParseBinaryResValue(
257e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski              ResourceType::kAnim, {}, parser->getStrings(), res_value, out_pool);
258e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski        }
259bbf429795d0558797e7ac8d1024fa5c16552e96cAdam Lesinski      }
260d0f492db038c6210c1138865d816bfb134376538Adam Lesinski
261ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      el->attributes.push_back(std::move(attr));
26275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
263ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
26475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
26575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
2668780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinskistd::unique_ptr<XmlResource> Inflate(const void* data, size_t len, std::string* out_error) {
267ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // We import the android namespace because on Windows NO_ERROR is a macro, not
2686b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  // an enum, which causes errors when qualifying it with android::
269ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  using namespace android;
270803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski
271e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  std::unique_ptr<XmlResource> xml_resource = util::make_unique<XmlResource>();
272e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski
2736b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::stack<Element*> node_stack;
2746b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::unique_ptr<Element> pending_element;
27575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
276ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ResXMLTree tree;
2778780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski  if (tree.setTo(data, len) != NO_ERROR) {
2788780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski    if (out_error != nullptr) {
2798780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski      *out_error = "failed to initialize ResXMLTree";
2808780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski    }
281ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return {};
282ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
283ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
284ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ResXMLParser::event_code_t code;
2856b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT && code != ResXMLParser::END_DOCUMENT) {
286ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<Node> new_node;
287ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    switch (code) {
288ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::START_NAMESPACE: {
2896b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        NamespaceDecl decl;
2901ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski        decl.line_number = tree.getLineNumber();
2911ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski
292ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        size_t len;
293ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const char16_t* str16 = tree.getNamespacePrefix(&len);
294ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
2956b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          decl.prefix = util::Utf16ToUtf8(StringPiece16(str16, len));
296ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
297ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
298ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        str16 = tree.getNamespaceUri(&len);
299ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
3006b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          decl.uri = util::Utf16ToUtf8(StringPiece16(str16, len));
3016b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        }
3026b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
3036b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        if (pending_element == nullptr) {
3046b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          pending_element = util::make_unique<Element>();
305ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
3061ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski        pending_element->namespace_decls.push_back(std::move(decl));
307ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
308ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
309ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
310ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::START_TAG: {
3116b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        std::unique_ptr<Element> el;
3126b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        if (pending_element != nullptr) {
3136b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          el = std::move(pending_element);
3146b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        } else {
3156b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          el = util::make_unique<Element>();
3166b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        }
3171ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski        el->line_number = tree.getLineNumber();
3186b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
319ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        size_t len;
320ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const char16_t* str16 = tree.getElementNamespace(&len);
321ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
3226b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          el->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
323ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
32475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
325ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        str16 = tree.getElementName(&len);
326ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
3276b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          el->name = util::Utf16ToUtf8(StringPiece16(str16, len));
32875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
32975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
3306b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        Element* this_el = el.get();
331e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski        CopyAttributes(el.get(), &tree, &xml_resource->string_pool);
332ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
3336b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        if (!node_stack.empty()) {
3346b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          node_stack.top()->AppendChild(std::move(el));
3356b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        } else {
336e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski          xml_resource->root = std::move(el);
3376b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        }
3386b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        node_stack.push(this_el);
339ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
340ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
341ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
342ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::TEXT: {
3436b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        std::unique_ptr<Text> text = util::make_unique<Text>();
3446b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        text->line_number = tree.getLineNumber();
345ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        size_t len;
346ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const char16_t* str16 = tree.getText(&len);
347ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
3486b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          text->text = util::Utf16ToUtf8(StringPiece16(str16, len));
34975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
3506b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        CHECK(!node_stack.empty());
3516b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        node_stack.top()->AppendChild(std::move(text));
352ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
353ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
354ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
355ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::END_NAMESPACE:
3566b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        break;
3576b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
358ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::END_TAG:
359ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        CHECK(!node_stack.empty());
360ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        node_stack.pop();
361ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
362ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
363ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      default:
364ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        LOG(FATAL) << "unhandled XML chunk type";
365ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
36675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
367ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
368e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski  return xml_resource;
3695eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
3705eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
3718780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinskistd::unique_ptr<XmlResource> XmlResource::Clone() const {
3728780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski  std::unique_ptr<XmlResource> cloned = util::make_unique<XmlResource>(file);
3738780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski  if (root != nullptr) {
3748780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski    cloned->root = root->CloneElement([&](const xml::Element& src, xml::Element* dst) {
3758780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski      dst->attributes.reserve(src.attributes.size());
3768780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski      for (const xml::Attribute& attr : src.attributes) {
3778780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski        xml::Attribute cloned_attr;
3788780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski        cloned_attr.name = attr.name;
3798780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski        cloned_attr.namespace_uri = attr.namespace_uri;
3808780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski        cloned_attr.value = attr.value;
3818780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski        cloned_attr.compiled_attribute = attr.compiled_attribute;
3828780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski        if (attr.compiled_value != nullptr) {
3838780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski          cloned_attr.compiled_value.reset(attr.compiled_value->Clone(&cloned->string_pool));
3848780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski        }
3858780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski        dst->attributes.push_back(std::move(cloned_attr));
3868780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski      }
3878780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski    });
3888780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski  }
3898780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski  return cloned;
3908780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski}
3918780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski
392ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* FindRootElement(Node* node) {
3936b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  if (node == nullptr) {
394ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return nullptr;
395ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
396ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
3976b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  while (node->parent != nullptr) {
3986b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    node = node->parent;
399ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
4006b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  return NodeCast<Element>(node);
401ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski}
402ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski
4036b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Element::AppendChild(std::unique_ptr<Node> child) {
404ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  child->parent = this;
405ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  children.push_back(std::move(child));
40675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
40775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
4086b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Element::InsertChild(size_t index, std::unique_ptr<Node> child) {
409e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski  child->parent = this;
410e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski  children.insert(children.begin() + index, std::move(child));
411e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski}
412e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski
4136b372991296c9f2bd6f8f8847dcd23d50970d06dAdam LesinskiAttribute* Element::FindAttribute(const StringPiece& ns, const StringPiece& name) {
4148780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski  return const_cast<Attribute*>(static_cast<const Element*>(this)->FindAttribute(ns, name));
41575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
41675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
417c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskiconst Attribute* Element::FindAttribute(const StringPiece& ns, const StringPiece& name) const {
418c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  for (const auto& attr : attributes) {
419c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    if (ns == attr.namespace_uri && name == attr.name) {
420c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      return &attr;
421c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    }
422c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  }
423c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  return nullptr;
424c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski}
425c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
426c6284379a5dde6bc5927409eff292db2f0add578Adam LesinskiAttribute* Element::FindOrCreateAttribute(const StringPiece& ns, const StringPiece& name) {
427c6284379a5dde6bc5927409eff292db2f0add578Adam Lesinski  Attribute* attr = FindAttribute(ns, name);
428c6284379a5dde6bc5927409eff292db2f0add578Adam Lesinski  if (attr == nullptr) {
429c6284379a5dde6bc5927409eff292db2f0add578Adam Lesinski    attributes.push_back(Attribute{ns.to_string(), name.to_string()});
430c6284379a5dde6bc5927409eff292db2f0add578Adam Lesinski    attr = &attributes.back();
431c6284379a5dde6bc5927409eff292db2f0add578Adam Lesinski  }
432c6284379a5dde6bc5927409eff292db2f0add578Adam Lesinski  return attr;
433c6284379a5dde6bc5927409eff292db2f0add578Adam Lesinski}
434c6284379a5dde6bc5927409eff292db2f0add578Adam Lesinski
435ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* Element::FindChild(const StringPiece& ns, const StringPiece& name) {
436ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return FindChildWithAttribute(ns, name, {}, {}, {});
43775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
43875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
4398780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinskiconst Element* Element::FindChild(const StringPiece& ns, const StringPiece& name) const {
4408780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski  return FindChildWithAttribute(ns, name, {}, {}, {});
4418780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski}
4428780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski
4436b372991296c9f2bd6f8f8847dcd23d50970d06dAdam LesinskiElement* Element::FindChildWithAttribute(const StringPiece& ns, const StringPiece& name,
4446b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski                                         const StringPiece& attr_ns, const StringPiece& attr_name,
445ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                         const StringPiece& attr_value) {
4468780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski  return const_cast<Element*>(static_cast<const Element*>(this)->FindChildWithAttribute(
4478780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski      ns, name, attr_ns, attr_name, attr_value));
4488780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski}
4498780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski
4508780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinskiconst Element* Element::FindChildWithAttribute(const StringPiece& ns, const StringPiece& name,
4518780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski                                               const StringPiece& attr_ns,
4528780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski                                               const StringPiece& attr_name,
4538780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski                                               const StringPiece& attr_value) const {
4548780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski  for (const auto& child : children) {
4558780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski    if (const Element* el = NodeCast<Element>(child.get())) {
456ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (ns == el->namespace_uri && name == el->name) {
457ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (attr_ns.empty() && attr_name.empty()) {
458ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          return el;
45975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
46075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
4618780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski        const Attribute* attr = el->FindAttribute(attr_ns, attr_name);
462ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (attr && attr_value == attr->value) {
463ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          return el;
46475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
465ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
46675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
467ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
468ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return nullptr;
46975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
47075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
471ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::vector<Element*> Element::GetChildElements() {
472ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<Element*> elements;
473ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (auto& child_node : children) {
4746b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    if (Element* child = NodeCast<Element>(child_node.get())) {
4756b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski      elements.push_back(child);
4765eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski    }
477ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
478ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return elements;
4795eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
4805eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
4816b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistd::unique_ptr<Node> Element::Clone(const ElementCloneFunc& el_cloner) const {
482ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  auto el = util::make_unique<Element>();
4836b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  el->namespace_decls = namespace_decls;
484ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->comment = comment;
485ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->line_number = line_number;
486ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->column_number = column_number;
487ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->name = name;
488ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->namespace_uri = namespace_uri;
489ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->attributes.reserve(attributes.size());
490c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  el_cloner(*this, el.get());
491ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->children.reserve(children.size());
492ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const std::unique_ptr<xml::Node>& child : children) {
493c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    el->AppendChild(child->Clone(el_cloner));
494ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
495ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return std::move(el);
4965eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
4975eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
4986b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistd::unique_ptr<Element> Element::CloneElement(const ElementCloneFunc& el_cloner) const {
4996b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  return std::unique_ptr<Element>(static_cast<Element*>(Clone(el_cloner).release()));
5006b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski}
5016b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
5026b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Element::Accept(Visitor* visitor) {
5036b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  visitor->BeforeVisitElement(this);
5046b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  visitor->Visit(this);
5056b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  visitor->AfterVisitElement(this);
5066b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski}
5076b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
508d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinskivoid Element::Accept(ConstVisitor* visitor) const {
509d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski  visitor->BeforeVisitElement(this);
510d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski  visitor->Visit(this);
511d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski  visitor->AfterVisitElement(this);
512d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski}
513d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski
5146b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistd::unique_ptr<Node> Text::Clone(const ElementCloneFunc&) const {
515ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  auto t = util::make_unique<Text>();
516ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->comment = comment;
517ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->line_number = line_number;
518ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->column_number = column_number;
519ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->text = text;
520ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return std::move(t);
521ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}
522467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
5236b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Text::Accept(Visitor* visitor) {
5246b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  visitor->Visit(this);
5256b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski}
526ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
527d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinskivoid Text::Accept(ConstVisitor* visitor) const {
528d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski  visitor->Visit(this);
529d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski}
530d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski
5316b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid PackageAwareVisitor::BeforeVisitElement(Element* el) {
5326b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::vector<PackageDecl> decls;
5336b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  for (const NamespaceDecl& decl : el->namespace_decls) {
5346b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    if (Maybe<ExtractedPackage> maybe_package = ExtractPackageFromNamespace(decl.uri)) {
5356b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski      decls.push_back(PackageDecl{decl.prefix, std::move(maybe_package.value())});
5366b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    }
537ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
5386b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  package_decls_.push_back(std::move(decls));
5396b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski}
5406b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
5416b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid PackageAwareVisitor::AfterVisitElement(Element* el) {
5426b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  package_decls_.pop_back();
543467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski}
544467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
5451ef0fa9d7242b1926543bc49e35905d1be02a781Adam LesinskiMaybe<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias(const StringPiece& alias) const {
546ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (alias.empty()) {
5471ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski    return ExtractedPackage{{}, false /*private*/};
548ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
549ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
550ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const auto rend = package_decls_.rend();
551ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) {
5526b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    const std::vector<PackageDecl>& decls = *iter;
5536b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    const auto rend2 = decls.rend();
5546b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    for (auto iter2 = decls.rbegin(); iter2 != rend2; ++iter2) {
5556b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski      const PackageDecl& decl = *iter2;
5566b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski      if (alias == decl.prefix) {
5576b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        if (decl.package.package.empty()) {
5581ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski          return ExtractedPackage{{}, decl.package.private_namespace};
5596b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        }
5606b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        return decl.package;
561ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
562ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    }
563ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
564ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return {};
565467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski}
566467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
567ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}  // namespace xml
568ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}  // namespace aapt
569