XmlDom.cpp revision 6b372991296c9f2bd6f8f8847dcd23d50970d06d
175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/*
275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Copyright (C) 2015 The Android Open Source Project
375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski *
475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * you may not use this file except in compliance with the License.
675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * You may obtain a copy of the License at
775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski *
875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski *
1075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Unless required by applicable law or agreed to in writing, software
1175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
1275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * See the License for the specific language governing permissions and
1475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * limitations under the License.
1575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
1675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
1775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include "XmlDom.h"
1875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
19467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include <expat.h>
20ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
2175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <memory>
2275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <stack>
2375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <string>
2475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <tuple>
2575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
26ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "android-base/logging.h"
27ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
28d0f492db038c6210c1138865d816bfb134376538Adam Lesinski#include "ResourceUtils.h"
29ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "XmlPullParser.h"
30ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "util/Util.h"
31ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
32efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinskiusing ::aapt::io::InputStream;
33efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinskiusing ::android::StringPiece;
34efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinskiusing ::android::StringPiece16;
35d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski
3675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace aapt {
3775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace xml {
3875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
3975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskiconstexpr char kXmlNamespaceSep = 1;
4075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
4175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistruct Stack {
426b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::unique_ptr<xml::Element> root;
436b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::stack<xml::Element*> node_stack;
446b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::unique_ptr<xml::Element> pending_element;
45ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string pending_comment;
46ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  std::unique_ptr<xml::Text> last_text_node;
4775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski};
4875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
496b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski// Extracts the namespace and name of an expanded element or attribute name.
506b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistatic void SplitName(const char* name, std::string* out_ns, std::string* out_name) {
51ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const char* p = name;
52ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  while (*p != 0 && *p != kXmlNamespaceSep) {
53ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    p++;
54ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
55ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
56ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (*p == 0) {
57ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    out_ns->clear();
58d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski    out_name->assign(name);
59ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  } else {
60d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski    out_ns->assign(name, (p - name));
61d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski    out_name->assign(p + 1);
62ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
6375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
6475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
65ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinskistatic void FinishPendingText(Stack* stack) {
66ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  if (stack->last_text_node != nullptr) {
6748448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski    if (!stack->last_text_node->text.empty()) {
686b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski      CHECK(!stack->node_stack.empty());
69ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski      stack->node_stack.top()->AppendChild(std::move(stack->last_text_node));
70ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski    } else {
71ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski      // Drop an empty text node.
72ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski    }
7348448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski    stack->last_text_node = nullptr;
74ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  }
75ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski}
76ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski
776b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistatic void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix, const char* uri) {
78ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
80ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  FinishPendingText(stack);
8175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
826b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  NamespaceDecl decl;
836b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  decl.line_number = XML_GetCurrentLineNumber(parser);
846b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  decl.column_number = XML_GetCurrentColumnNumber(parser);
856b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  decl.prefix = prefix ? prefix : "";
866b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  decl.uri = uri ? uri : "";
8775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
886b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  if (stack->pending_element == nullptr) {
896b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    stack->pending_element = util::make_unique<Element>();
90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
916b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  stack->pending_element->namespace_decls.push_back(std::move(decl));
9275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
9375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
946b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistatic void XMLCALL EndNamespaceHandler(void* user_data, const char* /*prefix*/) {
95ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
96ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
97ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  FinishPendingText(stack);
9875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
9975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
100ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic bool less_attribute(const Attribute& lhs, const Attribute& rhs) {
101ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return std::tie(lhs.namespace_uri, lhs.name, lhs.value) <
102ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski         std::tie(rhs.namespace_uri, rhs.name, rhs.value);
10375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
10475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
1056b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistatic void XMLCALL StartElementHandler(void* user_data, const char* name, const char** attrs) {
106ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
107ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
108ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  FinishPendingText(stack);
10975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
1106b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::unique_ptr<Element> el;
1116b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  if (stack->pending_element != nullptr) {
1126b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    el = std::move(stack->pending_element);
1136b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  } else {
1146b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    el = util::make_unique<Element>();
1156b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  }
1166b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
1176b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  el->line_number = XML_GetCurrentLineNumber(parser);
1186b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  el->column_number = XML_GetCurrentColumnNumber(parser);
1196b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  el->comment = std::move(stack->pending_comment);
1206b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
121ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  SplitName(name, &el->namespace_uri, &el->name);
12275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
123ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  while (*attrs) {
124ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    Attribute attribute;
125ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    SplitName(*attrs++, &attribute.namespace_uri, &attribute.name);
12648448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski    attribute.value = *attrs++;
1276b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    el->attributes.push_back(std::move(attribute));
128ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
12975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
1306b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  // Sort the attributes.
1316b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::sort(el->attributes.begin(), el->attributes.end(), less_attribute);
1326b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
1336b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  // Add to the stack.
1346b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  Element* this_el = el.get();
1356b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  if (!stack->node_stack.empty()) {
1366b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    stack->node_stack.top()->AppendChild(std::move(el));
1376b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  } else {
1386b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    stack->root = std::move(el);
1396b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  }
1406b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  stack->node_stack.push(this_el);
14175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
14275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
143ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL EndElementHandler(void* user_data, const char* name) {
144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
145ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
146ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  FinishPendingText(stack);
14775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
148ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  CHECK(!stack->node_stack.empty());
149ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // stack->nodeStack.top()->comment = std::move(stack->pendingComment);
150ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  stack->node_stack.pop();
15175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
15275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
153ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinskistatic void XMLCALL CharacterDataHandler(void* user_data, const char* s, int len) {
154ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
155ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
156ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
157ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  const StringPiece str(s, len);
158ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  if (str.empty()) {
159ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return;
160ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
161ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
162ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // See if we can just append the text to a previous text node.
163ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  if (stack->last_text_node != nullptr) {
16448448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski    stack->last_text_node->text.append(str.data(), str.size());
165ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski    return;
166ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
16775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
168ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  stack->last_text_node = util::make_unique<Text>();
169ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  stack->last_text_node->line_number = XML_GetCurrentLineNumber(parser);
170ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  stack->last_text_node->column_number = XML_GetCurrentColumnNumber(parser);
17148448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski  stack->last_text_node->text = str.to_string();
17275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
17375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
174ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL CommentDataHandler(void* user_data, const char* comment) {
175ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
176ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
177ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski  FinishPendingText(stack);
17875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
179ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!stack->pending_comment.empty()) {
180ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    stack->pending_comment += '\n';
181ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
182ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  stack->pending_comment += comment;
18375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
18475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
185efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinskistd::unique_ptr<XmlResource> Inflate(InputStream* in, IDiagnostics* diag, const Source& source) {
186ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack stack;
187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
188efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  std::unique_ptr<std::remove_pointer<XML_Parser>::type, decltype(XML_ParserFree)*> parser = {
189efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski      XML_ParserCreateNS(nullptr, kXmlNamespaceSep), XML_ParserFree};
190efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  XML_SetUserData(parser.get(), &stack);
191efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  XML_UseParserAsHandlerArg(parser.get());
192efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  XML_SetElementHandler(parser.get(), StartElementHandler, EndElementHandler);
193efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  XML_SetNamespaceDeclHandler(parser.get(), StartNamespaceHandler, EndNamespaceHandler);
194efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  XML_SetCharacterDataHandler(parser.get(), CharacterDataHandler);
195efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  XML_SetCommentHandler(parser.get(), CommentDataHandler);
196efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski
197efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  const char* buffer = nullptr;
198efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  size_t buffer_size = 0;
199efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  while (in->Next(reinterpret_cast<const void**>(&buffer), &buffer_size)) {
200efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski    if (XML_Parse(parser.get(), buffer, buffer_size, false) == XML_STATUS_ERROR) {
201efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski      diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser.get())))
202efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski                  << XML_ErrorString(XML_GetErrorCode(parser.get())));
203efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski      return {};
2041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
205ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
206ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
207efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  if (in->HadError()) {
208efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski    diag->Error(DiagMessage(source) << in->GetError());
209efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski    return {};
210efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  } else {
211efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski    // Finish off the parsing.
212efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski    if (XML_Parse(parser.get(), nullptr, 0u, true) == XML_STATUS_ERROR) {
213efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski      diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser.get())))
214efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski                  << XML_ErrorString(XML_GetErrorCode(parser.get())));
215efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski      return {};
216efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski    }
217ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
218efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski  return util::make_unique<XmlResource>(ResourceFile{{}, {}, source}, StringPool{},
219efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski                                        std::move(stack.root));
22075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
22175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
222d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic void CopyAttributes(Element* el, android::ResXMLParser* parser, StringPool* out_pool) {
223ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const size_t attr_count = parser->getAttributeCount();
224ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (attr_count > 0) {
225ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    el->attributes.reserve(attr_count);
226ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (size_t i = 0; i < attr_count; i++) {
227ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      Attribute attr;
228ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      size_t len;
229ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      const char16_t* str16 = parser->getAttributeNamespace(i, &len);
230ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (str16) {
231ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        attr.namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
232ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
233ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
234ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      str16 = parser->getAttributeName(i, &len);
235ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (str16) {
236ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        attr.name = util::Utf16ToUtf8(StringPiece16(str16, len));
237ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
238ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
239ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      str16 = parser->getAttributeStringValue(i, &len);
240ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (str16) {
241ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        attr.value = util::Utf16ToUtf8(StringPiece16(str16, len));
242ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
243d0f492db038c6210c1138865d816bfb134376538Adam Lesinski
244d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      android::Res_value res_value;
245d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      if (parser->getAttributeValue(i, &res_value) > 0) {
246d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        attr.compiled_value = ResourceUtils::ParseBinaryResValue(
247d0f492db038c6210c1138865d816bfb134376538Adam Lesinski            ResourceType::kAnim, {}, parser->getStrings(), res_value, out_pool);
248d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      }
249d0f492db038c6210c1138865d816bfb134376538Adam Lesinski
250ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      el->attributes.push_back(std::move(attr));
25175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
252ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
25375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
25475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
255d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistd::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len, IDiagnostics* diag,
256d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                     const Source& source) {
257ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // We import the android namespace because on Windows NO_ERROR is a macro, not
2586b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  // an enum, which causes errors when qualifying it with android::
259ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  using namespace android;
260803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski
261d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  StringPool string_pool;
2626b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::unique_ptr<Element> root;
2636b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::stack<Element*> node_stack;
2646b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::unique_ptr<Element> pending_element;
26575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
266ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ResXMLTree tree;
267ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (tree.setTo(data, data_len) != NO_ERROR) {
268ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return {};
269ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
270ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
271ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ResXMLParser::event_code_t code;
2726b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT && code != ResXMLParser::END_DOCUMENT) {
273ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<Node> new_node;
274ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    switch (code) {
275ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::START_NAMESPACE: {
2766b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        NamespaceDecl decl;
277ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        size_t len;
278ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const char16_t* str16 = tree.getNamespacePrefix(&len);
279ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
2806b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          decl.prefix = util::Utf16ToUtf8(StringPiece16(str16, len));
281ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
282ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
283ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        str16 = tree.getNamespaceUri(&len);
284ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
2856b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          decl.uri = util::Utf16ToUtf8(StringPiece16(str16, len));
2866b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        }
2876b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
2886b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        if (pending_element == nullptr) {
2896b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          pending_element = util::make_unique<Element>();
290ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
291ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
292ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
293ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
294ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::START_TAG: {
2956b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        std::unique_ptr<Element> el;
2966b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        if (pending_element != nullptr) {
2976b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          el = std::move(pending_element);
2986b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        } else {
2996b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          el = util::make_unique<Element>();
3006b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          ;
3016b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        }
3026b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
303ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        size_t len;
304ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const char16_t* str16 = tree.getElementNamespace(&len);
305ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
3066b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          el->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
307ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
30875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
309ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        str16 = tree.getElementName(&len);
310ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
3116b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          el->name = util::Utf16ToUtf8(StringPiece16(str16, len));
31275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
31375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
3146b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        Element* this_el = el.get();
3156b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        CopyAttributes(el.get(), &tree, &string_pool);
316ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
3176b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        if (!node_stack.empty()) {
3186b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          node_stack.top()->AppendChild(std::move(el));
3196b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        } else {
3206b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          root = std::move(el);
3216b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        }
3226b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        node_stack.push(this_el);
323ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
324ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
325ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
326ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::TEXT: {
3276b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        std::unique_ptr<Text> text = util::make_unique<Text>();
3286b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        text->line_number = tree.getLineNumber();
329ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        size_t len;
330ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const char16_t* str16 = tree.getText(&len);
331ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
3326b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          text->text = util::Utf16ToUtf8(StringPiece16(str16, len));
33375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
3346b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        CHECK(!node_stack.empty());
3356b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        node_stack.top()->AppendChild(std::move(text));
336ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
337ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
338ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
339ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::END_NAMESPACE:
3406b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        break;
3416b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
342ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::END_TAG:
343ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        CHECK(!node_stack.empty());
344ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        node_stack.pop();
345ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
346ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
347ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      default:
348ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        LOG(FATAL) << "unhandled XML chunk type";
349ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
35075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
351ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
352ea134e08d70d156bdd17714d5f9ab9c44c91d4faAdam Lesinski  return util::make_unique<XmlResource>(ResourceFile{}, std::move(string_pool), std::move(root));
3535eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
3545eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
355ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* FindRootElement(Node* node) {
3566b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  if (node == nullptr) {
357ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return nullptr;
358ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
359ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
3606b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  while (node->parent != nullptr) {
3616b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    node = node->parent;
362ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
3636b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  return NodeCast<Element>(node);
364ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski}
365ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski
3666b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Element::AppendChild(std::unique_ptr<Node> child) {
367ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  child->parent = this;
368ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  children.push_back(std::move(child));
36975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
37075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
3716b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Element::InsertChild(size_t index, std::unique_ptr<Node> child) {
372e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski  child->parent = this;
373e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski  children.insert(children.begin() + index, std::move(child));
374e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski}
375e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski
3766b372991296c9f2bd6f8f8847dcd23d50970d06dAdam LesinskiAttribute* Element::FindAttribute(const StringPiece& ns, const StringPiece& name) {
377ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (auto& attr : attributes) {
378ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (ns == attr.namespace_uri && name == attr.name) {
379ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return &attr;
38075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
381ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
382ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return nullptr;
38375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
38475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
385c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskiconst Attribute* Element::FindAttribute(const StringPiece& ns, const StringPiece& name) const {
386c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  for (const auto& attr : attributes) {
387c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    if (ns == attr.namespace_uri && name == attr.name) {
388c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski      return &attr;
389c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    }
390c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  }
391c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  return nullptr;
392c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski}
393c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski
394ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* Element::FindChild(const StringPiece& ns, const StringPiece& name) {
395ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return FindChildWithAttribute(ns, name, {}, {}, {});
39675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
39775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
3986b372991296c9f2bd6f8f8847dcd23d50970d06dAdam LesinskiElement* Element::FindChildWithAttribute(const StringPiece& ns, const StringPiece& name,
3996b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski                                         const StringPiece& attr_ns, const StringPiece& attr_name,
400ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                         const StringPiece& attr_value) {
4016b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  for (auto& child : children) {
4026b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    if (Element* el = NodeCast<Element>(child.get())) {
403ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (ns == el->namespace_uri && name == el->name) {
404ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (attr_ns.empty() && attr_name.empty()) {
405ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          return el;
40675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
40775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
408ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        Attribute* attr = el->FindAttribute(attr_ns, attr_name);
409ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (attr && attr_value == attr->value) {
410ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          return el;
41175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
412ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
41375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
414ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
415ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return nullptr;
41675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
41775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
418ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::vector<Element*> Element::GetChildElements() {
419ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<Element*> elements;
420ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (auto& child_node : children) {
4216b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    if (Element* child = NodeCast<Element>(child_node.get())) {
4226b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski      elements.push_back(child);
4235eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski    }
424ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
425ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return elements;
4265eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
4275eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
4286b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistd::unique_ptr<Node> Element::Clone(const ElementCloneFunc& el_cloner) const {
429ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  auto el = util::make_unique<Element>();
4306b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  el->namespace_decls = namespace_decls;
431ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->comment = comment;
432ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->line_number = line_number;
433ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->column_number = column_number;
434ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->name = name;
435ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->namespace_uri = namespace_uri;
436ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->attributes.reserve(attributes.size());
437c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski  el_cloner(*this, el.get());
438ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->children.reserve(children.size());
439ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const std::unique_ptr<xml::Node>& child : children) {
440c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski    el->AppendChild(child->Clone(el_cloner));
441ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
442ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return std::move(el);
4435eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
4445eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
4456b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistd::unique_ptr<Element> Element::CloneElement(const ElementCloneFunc& el_cloner) const {
4466b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  return std::unique_ptr<Element>(static_cast<Element*>(Clone(el_cloner).release()));
4476b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski}
4486b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
4496b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Element::Accept(Visitor* visitor) {
4506b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  visitor->BeforeVisitElement(this);
4516b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  visitor->Visit(this);
4526b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  visitor->AfterVisitElement(this);
4536b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski}
4546b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
4556b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistd::unique_ptr<Node> Text::Clone(const ElementCloneFunc&) const {
456ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  auto t = util::make_unique<Text>();
457ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->comment = comment;
458ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->line_number = line_number;
459ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->column_number = column_number;
460ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->text = text;
461ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return std::move(t);
462ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}
463467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
4646b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Text::Accept(Visitor* visitor) {
4656b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  visitor->Visit(this);
4666b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski}
467ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
4686b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid PackageAwareVisitor::BeforeVisitElement(Element* el) {
4696b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  std::vector<PackageDecl> decls;
4706b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  for (const NamespaceDecl& decl : el->namespace_decls) {
4716b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    if (Maybe<ExtractedPackage> maybe_package = ExtractPackageFromNamespace(decl.uri)) {
4726b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski      decls.push_back(PackageDecl{decl.prefix, std::move(maybe_package.value())});
4736b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    }
474ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
4756b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  package_decls_.push_back(std::move(decls));
4766b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski}
4776b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski
4786b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid PackageAwareVisitor::AfterVisitElement(Element* el) {
4796b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski  package_decls_.pop_back();
480467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski}
481467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
482ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiMaybe<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias(
483ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const StringPiece& alias, const StringPiece& local_package) const {
484ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (alias.empty()) {
485d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski    return ExtractedPackage{local_package.to_string(), false /* private */};
486ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
487ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
488ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const auto rend = package_decls_.rend();
489ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) {
4906b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    const std::vector<PackageDecl>& decls = *iter;
4916b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    const auto rend2 = decls.rend();
4926b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski    for (auto iter2 = decls.rbegin(); iter2 != rend2; ++iter2) {
4936b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski      const PackageDecl& decl = *iter2;
4946b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski      if (alias == decl.prefix) {
4956b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        if (decl.package.package.empty()) {
4966b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski          return ExtractedPackage{local_package.to_string(), decl.package.private_namespace};
4976b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        }
4986b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski        return decl.package;
499ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
500ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    }
501ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
502ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return {};
503467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski}
504467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
505ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}  // namespace xml
506ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}  // namespace aapt
507