XmlDom.cpp revision 8780eb6e4918ae24fb1ae74d631042c32e41dc3d
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));
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
2618780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinskistd::unique_ptr<XmlResource> Inflate(const void* data, size_t len, std::string* out_error) {
262ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // We import the android namespace because on Windows NO_ERROR is a macro, not
2636b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  // an enum, which causes errors when qualifying it with android::
264ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  using namespace android;
265803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski
266d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  StringPool string_pool;
2676b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::unique_ptr<Element> root;
2686b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::stack<Element*> node_stack;
2696b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::unique_ptr<Element> pending_element;
27075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
271ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ResXMLTree tree;
2728780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski  if (tree.setTo(data, len) != NO_ERROR) {
2738780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski    if (out_error != nullptr) {
2748780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski      *out_error = "failed to initialize ResXMLTree";
2758780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski    }
276ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return {};
277ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
278ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
279ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ResXMLParser::event_code_t code;
2806b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT && code != ResXMLParser::END_DOCUMENT) {
281ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<Node> new_node;
282ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    switch (code) {
283ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::START_NAMESPACE: {
2846b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        NamespaceDecl decl;
2851ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski        decl.line_number = tree.getLineNumber();
2861ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski
287ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        size_t len;
288ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const char16_t* str16 = tree.getNamespacePrefix(&len);
289ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
2906b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          decl.prefix = util::Utf16ToUtf8(StringPiece16(str16, len));
291ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
292ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
293ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        str16 = tree.getNamespaceUri(&len);
294ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
2956b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          decl.uri = util::Utf16ToUtf8(StringPiece16(str16, len));
2966b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        }
2976b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
2986b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        if (pending_element == nullptr) {
2996b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          pending_element = util::make_unique<Element>();
300ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
3011ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski        pending_element->namespace_decls.push_back(std::move(decl));
302ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
303ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
304ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
305ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::START_TAG: {
3066b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        std::unique_ptr<Element> el;
3076b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        if (pending_element != nullptr) {
3086b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          el = std::move(pending_element);
3096b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        } else {
3106b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          el = util::make_unique<Element>();
3116b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        }
3121ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski        el->line_number = tree.getLineNumber();
3136b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
314ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        size_t len;
315ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const char16_t* str16 = tree.getElementNamespace(&len);
316ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
3176b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          el->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
318ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
31975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
320ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        str16 = tree.getElementName(&len);
321ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
3226b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          el->name = util::Utf16ToUtf8(StringPiece16(str16, len));
32375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
32475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
3256b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        Element* this_el = el.get();
3266b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        CopyAttributes(el.get(), &tree, &string_pool);
327ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
3286b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        if (!node_stack.empty()) {
3296b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          node_stack.top()->AppendChild(std::move(el));
3306b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        } else {
3316b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          root = std::move(el);
3326b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        }
3336b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        node_stack.push(this_el);
334ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
335ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
336ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
337ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::TEXT: {
3386b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        std::unique_ptr<Text> text = util::make_unique<Text>();
3396b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        text->line_number = tree.getLineNumber();
340ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        size_t len;
341ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const char16_t* str16 = tree.getText(&len);
342ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
3436b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          text->text = util::Utf16ToUtf8(StringPiece16(str16, len));
34475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
3456b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        CHECK(!node_stack.empty());
3466b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        node_stack.top()->AppendChild(std::move(text));
347ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
348ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
349ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
350ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::END_NAMESPACE:
3516b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        break;
3526b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
353ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::END_TAG:
354ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        CHECK(!node_stack.empty());
355ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        node_stack.pop();
356ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
357ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
358ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      default:
359ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        LOG(FATAL) << "unhandled XML chunk type";
360ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
36175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
362ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
363ea134e08d70d156bdd17714d5f9ab9c44c91d4faAdam Lesinski  return util::make_unique<XmlResource>(ResourceFile{}, std::move(string_pool), std::move(root));
3645eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
3655eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
3668780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinskistd::unique_ptr<XmlResource> XmlResource::Clone() const {
3678780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski  std::unique_ptr<XmlResource> cloned = util::make_unique<XmlResource>(file);
3688780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski  if (root != nullptr) {
3698780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski    cloned->root = root->CloneElement([&](const xml::Element& src, xml::Element* dst) {
3708780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski      dst->attributes.reserve(src.attributes.size());
3718780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski      for (const xml::Attribute& attr : src.attributes) {
3728780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski        xml::Attribute cloned_attr;
3738780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski        cloned_attr.name = attr.name;
3748780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski        cloned_attr.namespace_uri = attr.namespace_uri;
3758780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski        cloned_attr.value = attr.value;
3768780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski        cloned_attr.compiled_attribute = attr.compiled_attribute;
3778780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski        if (attr.compiled_value != nullptr) {
3788780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski          cloned_attr.compiled_value.reset(attr.compiled_value->Clone(&cloned->string_pool));
3798780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski        }
3808780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski        dst->attributes.push_back(std::move(cloned_attr));
3818780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski      }
3828780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski    });
3838780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski  }
3848780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski  return cloned;
3858780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski}
3868780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski
387ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* FindRootElement(Node* node) {
3886b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  if (node == nullptr) {
389ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return nullptr;
390ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
391ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
3926b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  while (node->parent != nullptr) {
3936b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    node = node->parent;
394ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
3956b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  return NodeCast<Element>(node);
396ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski}
397ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski
3986b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Element::AppendChild(std::unique_ptr<Node> child) {
399ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  child->parent = this;
400ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  children.push_back(std::move(child));
40175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
40275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
4036b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Element::InsertChild(size_t index, std::unique_ptr<Node> child) {
404e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski  child->parent = this;
405e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski  children.insert(children.begin() + index, std::move(child));
406e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski}
407e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski
4086b372991296c9f2bd6f8f8847dcd23d50970d06dAdam LesinskiAttribute* Element::FindAttribute(const StringPiece& ns, const StringPiece& name) {
4098780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski  return const_cast<Attribute*>(static_cast<const Element*>(this)->FindAttribute(ns, name));
41075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
41175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
412c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskiconst Attribute* Element::FindAttribute(const StringPiece& ns, const StringPiece& name) const {
413c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  for (const auto& attr : attributes) {
414c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    if (ns == attr.namespace_uri && name == attr.name) {
415c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      return &attr;
416c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    }
417c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  }
418c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  return nullptr;
419c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski}
420c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
421ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* Element::FindChild(const StringPiece& ns, const StringPiece& name) {
422ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return FindChildWithAttribute(ns, name, {}, {}, {});
42375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
42475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
4258780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinskiconst Element* Element::FindChild(const StringPiece& ns, const StringPiece& name) const {
4268780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski  return FindChildWithAttribute(ns, name, {}, {}, {});
4278780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski}
4288780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski
4296b372991296c9f2bd6f8f8847dcd23d50970d06dAdam LesinskiElement* Element::FindChildWithAttribute(const StringPiece& ns, const StringPiece& name,
4306b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski                                         const StringPiece& attr_ns, const StringPiece& attr_name,
431ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                         const StringPiece& attr_value) {
4328780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski  return const_cast<Element*>(static_cast<const Element*>(this)->FindChildWithAttribute(
4338780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski      ns, name, attr_ns, attr_name, attr_value));
4348780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski}
4358780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski
4368780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinskiconst Element* Element::FindChildWithAttribute(const StringPiece& ns, const StringPiece& name,
4378780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski                                               const StringPiece& attr_ns,
4388780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski                                               const StringPiece& attr_name,
4398780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski                                               const StringPiece& attr_value) const {
4408780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski  for (const auto& child : children) {
4418780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski    if (const Element* el = NodeCast<Element>(child.get())) {
442ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (ns == el->namespace_uri && name == el->name) {
443ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (attr_ns.empty() && attr_name.empty()) {
444ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          return el;
44575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
44675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
4478780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski        const Attribute* attr = el->FindAttribute(attr_ns, attr_name);
448ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (attr && attr_value == attr->value) {
449ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          return el;
45075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
451ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
45275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
453ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
454ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return nullptr;
45575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
45675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
457ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::vector<Element*> Element::GetChildElements() {
458ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<Element*> elements;
459ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (auto& child_node : children) {
4606b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    if (Element* child = NodeCast<Element>(child_node.get())) {
4616b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski      elements.push_back(child);
4625eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski    }
463ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
464ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return elements;
4655eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
4665eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
4676b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistd::unique_ptr<Node> Element::Clone(const ElementCloneFunc& el_cloner) const {
468ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  auto el = util::make_unique<Element>();
4696b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  el->namespace_decls = namespace_decls;
470ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->comment = comment;
471ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->line_number = line_number;
472ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->column_number = column_number;
473ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->name = name;
474ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->namespace_uri = namespace_uri;
475ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->attributes.reserve(attributes.size());
476c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  el_cloner(*this, el.get());
477ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->children.reserve(children.size());
478ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const std::unique_ptr<xml::Node>& child : children) {
479c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    el->AppendChild(child->Clone(el_cloner));
480ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
481ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return std::move(el);
4825eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
4835eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
4846b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistd::unique_ptr<Element> Element::CloneElement(const ElementCloneFunc& el_cloner) const {
4856b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  return std::unique_ptr<Element>(static_cast<Element*>(Clone(el_cloner).release()));
4866b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski}
4876b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
4886b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Element::Accept(Visitor* visitor) {
4896b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  visitor->BeforeVisitElement(this);
4906b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  visitor->Visit(this);
4916b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  visitor->AfterVisitElement(this);
4926b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski}
4936b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
494d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinskivoid Element::Accept(ConstVisitor* visitor) const {
495d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski  visitor->BeforeVisitElement(this);
496d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski  visitor->Visit(this);
497d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski  visitor->AfterVisitElement(this);
498d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski}
499d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski
5006b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistd::unique_ptr<Node> Text::Clone(const ElementCloneFunc&) const {
501ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  auto t = util::make_unique<Text>();
502ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->comment = comment;
503ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->line_number = line_number;
504ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->column_number = column_number;
505ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->text = text;
506ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return std::move(t);
507ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}
508467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
5096b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Text::Accept(Visitor* visitor) {
5106b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  visitor->Visit(this);
5116b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski}
512ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
513d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinskivoid Text::Accept(ConstVisitor* visitor) const {
514d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski  visitor->Visit(this);
515d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski}
516d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski
5176b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid PackageAwareVisitor::BeforeVisitElement(Element* el) {
5186b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::vector<PackageDecl> decls;
5196b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  for (const NamespaceDecl& decl : el->namespace_decls) {
5206b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    if (Maybe<ExtractedPackage> maybe_package = ExtractPackageFromNamespace(decl.uri)) {
5216b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski      decls.push_back(PackageDecl{decl.prefix, std::move(maybe_package.value())});
5226b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    }
523ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
5246b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  package_decls_.push_back(std::move(decls));
5256b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski}
5266b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
5276b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid PackageAwareVisitor::AfterVisitElement(Element* el) {
5286b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  package_decls_.pop_back();
529467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski}
530467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
5311ef0fa9d7242b1926543bc49e35905d1be02a781Adam LesinskiMaybe<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias(const StringPiece& alias) const {
532ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (alias.empty()) {
5331ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski    return ExtractedPackage{{}, false /*private*/};
534ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
535ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
536ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const auto rend = package_decls_.rend();
537ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) {
5386b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    const std::vector<PackageDecl>& decls = *iter;
5396b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    const auto rend2 = decls.rend();
5406b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    for (auto iter2 = decls.rbegin(); iter2 != rend2; ++iter2) {
5416b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski      const PackageDecl& decl = *iter2;
5426b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski      if (alias == decl.prefix) {
5436b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        if (decl.package.package.empty()) {
5441ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski          return ExtractedPackage{{}, decl.package.private_namespace};
5456b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        }
5466b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        return decl.package;
547ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
548ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    }
549ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
550ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return {};
551467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski}
552467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
553ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}  // namespace xml
554ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}  // namespace aapt
555