XmlDom.cpp revision ce5e56e243d262a9b65459c3bd0bb9eaadd40628
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
21ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <cassert>
2275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <memory>
2375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <stack>
2475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <string>
2575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <tuple>
2675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
27ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "android-base/logging.h"
28ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
29ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "XmlPullParser.h"
30ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "util/Util.h"
31ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
3275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace aapt {
3375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace xml {
3475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
3575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskiconstexpr char kXmlNamespaceSep = 1;
3675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
3775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistruct Stack {
38ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<xml::Node> root;
39ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::stack<xml::Node*> node_stack;
40ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::string pending_comment;
4175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski};
4275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
4375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/**
4475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Extracts the namespace and name of an expanded element or attribute name.
4575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */
46ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void SplitName(const char* name, std::string* out_ns,
47ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                      std::string* out_name) {
48ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const char* p = name;
49ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  while (*p != 0 && *p != kXmlNamespaceSep) {
50ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    p++;
51ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
52ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
53ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (*p == 0) {
54ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    out_ns->clear();
55ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    *out_name = StringPiece(name).ToString();
56ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  } else {
57ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    *out_ns = StringPiece(name, (p - name)).ToString();
58ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    *out_name = StringPiece(p + 1).ToString();
59ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
6075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
6175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
62ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void AddToStack(Stack* stack, XML_Parser parser,
63ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                       std::unique_ptr<Node> node) {
64ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  node->line_number = XML_GetCurrentLineNumber(parser);
65ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  node->column_number = XML_GetCurrentColumnNumber(parser);
66ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
67ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Node* this_node = node.get();
68ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!stack->node_stack.empty()) {
69ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    stack->node_stack.top()->AddChild(std::move(node));
70ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  } else {
71ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    stack->root = std::move(node);
72ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
73ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
74ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!NodeCast<Text>(this_node)) {
75ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    stack->node_stack.push(this_node);
76ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
7775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
7875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix,
80ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                          const char* uri) {
81ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
82ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
8375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
84ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<Namespace> ns = util::make_unique<Namespace>();
85ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (prefix) {
86ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    ns->namespace_prefix = StringPiece(prefix).ToString();
87ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
8875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
89ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (uri) {
90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    ns->namespace_uri = StringPiece(uri).ToString();
91ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
9275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
93ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  AddToStack(stack, parser, std::move(ns));
9475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
9575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
96ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL EndNamespaceHandler(void* user_data, const char* prefix) {
97ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
98ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
9975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
100ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  CHECK(!stack->node_stack.empty());
101ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  stack->node_stack.pop();
10275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
10375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
104ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic bool less_attribute(const Attribute& lhs, const Attribute& rhs) {
105ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return std::tie(lhs.namespace_uri, lhs.name, lhs.value) <
106ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski         std::tie(rhs.namespace_uri, rhs.name, rhs.value);
10775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
10875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
109ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL StartElementHandler(void* user_data, const char* name,
110ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                        const char** attrs) {
111ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
112ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
11375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
114ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<Element> el = util::make_unique<Element>();
115ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  SplitName(name, &el->namespace_uri, &el->name);
11675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
117ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  while (*attrs) {
118ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    Attribute attribute;
119ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    SplitName(*attrs++, &attribute.namespace_uri, &attribute.name);
120ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    attribute.value = StringPiece(*attrs++).ToString();
12175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
122ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    // Insert in sorted order.
123ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    auto iter = std::lower_bound(el->attributes.begin(), el->attributes.end(),
124ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                 attribute, less_attribute);
125ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    el->attributes.insert(iter, std::move(attribute));
126ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
12775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
128ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->comment = std::move(stack->pending_comment);
129ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  AddToStack(stack, parser, std::move(el));
13075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
13175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
132ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL EndElementHandler(void* user_data, const char* name) {
133ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
134ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
13575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
136ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  CHECK(!stack->node_stack.empty());
137ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // stack->nodeStack.top()->comment = std::move(stack->pendingComment);
138ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  stack->node_stack.pop();
13975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
14075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
141ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL CharacterDataHandler(void* user_data, const char* s,
142ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                         int len) {
143ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
145ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
146ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!s || len <= 0) {
147ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return;
148ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
149ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
150ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // See if we can just append the text to a previous text node.
151ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!stack->node_stack.empty()) {
152ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    Node* currentParent = stack->node_stack.top();
153ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (!currentParent->children.empty()) {
154ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      Node* last_child = currentParent->children.back().get();
155ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (Text* text = NodeCast<Text>(last_child)) {
156ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        text->text += StringPiece(s, len).ToString();
15775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        return;
158ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
15975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
160ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
16175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
162ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<Text> text = util::make_unique<Text>();
163ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  text->text = StringPiece(s, len).ToString();
164ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  AddToStack(stack, parser, std::move(text));
16575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
16675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
167ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL CommentDataHandler(void* user_data, const char* comment) {
168ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
169ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
17075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
171ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!stack->pending_comment.empty()) {
172ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    stack->pending_comment += '\n';
173ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
174ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  stack->pending_comment += comment;
17575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
17675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
177ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<XmlResource> Inflate(std::istream* in, IDiagnostics* diag,
178ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                     const Source& source) {
179ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Stack stack;
180ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
181ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_Parser parser = XML_ParserCreateNS(nullptr, kXmlNamespaceSep);
182ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_SetUserData(parser, &stack);
183ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_UseParserAsHandlerArg(parser);
184ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_SetElementHandler(parser, StartElementHandler, EndElementHandler);
185ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_SetNamespaceDeclHandler(parser, StartNamespaceHandler,
186ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                              EndNamespaceHandler);
187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_SetCharacterDataHandler(parser, CharacterDataHandler);
188ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_SetCommentHandler(parser, CommentDataHandler);
189ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
190ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  char buffer[1024];
191ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  while (!in->eof()) {
192ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    in->read(buffer, sizeof(buffer) / sizeof(buffer[0]));
193ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (in->bad() && !in->eof()) {
194ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      stack.root = {};
195ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      diag->Error(DiagMessage(source) << strerror(errno));
196ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      break;
19775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
19875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
199ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (XML_Parse(parser, buffer, in->gcount(), in->eof()) ==
200ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        XML_STATUS_ERROR) {
201ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      stack.root = {};
202ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser)))
203ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                  << XML_ErrorString(XML_GetErrorCode(parser)));
204ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      break;
2051ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
206ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
207ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
208ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  XML_ParserFree(parser);
209ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (stack.root) {
210ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return util::make_unique<XmlResource>(ResourceFile{{}, {}, source},
211ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                          std::move(stack.root));
212ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
213ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return {};
21475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
21575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
216ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void CopyAttributes(Element* el, android::ResXMLParser* parser) {
217ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const size_t attr_count = parser->getAttributeCount();
218ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (attr_count > 0) {
219ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    el->attributes.reserve(attr_count);
220ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    for (size_t i = 0; i < attr_count; i++) {
221ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      Attribute attr;
222ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      size_t len;
223ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      const char16_t* str16 = parser->getAttributeNamespace(i, &len);
224ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (str16) {
225ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        attr.namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
226ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
227ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
228ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      str16 = parser->getAttributeName(i, &len);
229ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (str16) {
230ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        attr.name = util::Utf16ToUtf8(StringPiece16(str16, len));
231ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
232ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
233ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      str16 = parser->getAttributeStringValue(i, &len);
234ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (str16) {
235ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        attr.value = util::Utf16ToUtf8(StringPiece16(str16, len));
236ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
237ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      el->attributes.push_back(std::move(attr));
23875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
239ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
24075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
24175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
242ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len,
243ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                     IDiagnostics* diag, const Source& source) {
244ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // We import the android namespace because on Windows NO_ERROR is a macro, not
245ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // an enum, which
246ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // causes errors when qualifying it with android::
247ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  using namespace android;
248803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski
249ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::unique_ptr<Node> root;
250ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::stack<Node*> node_stack;
25175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
252ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ResXMLTree tree;
253ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (tree.setTo(data, data_len) != NO_ERROR) {
254ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return {};
255ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
256ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
257ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ResXMLParser::event_code_t code;
258ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT &&
259ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski         code != ResXMLParser::END_DOCUMENT) {
260ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    std::unique_ptr<Node> new_node;
261ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    switch (code) {
262ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::START_NAMESPACE: {
263ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        std::unique_ptr<Namespace> node = util::make_unique<Namespace>();
264ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        size_t len;
265ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const char16_t* str16 = tree.getNamespacePrefix(&len);
266ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
267ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          node->namespace_prefix = util::Utf16ToUtf8(StringPiece16(str16, len));
268ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
269ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
270ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        str16 = tree.getNamespaceUri(&len);
271ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
272ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
273ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
274ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        new_node = std::move(node);
275ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
276ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
277ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
278ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::START_TAG: {
279ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        std::unique_ptr<Element> node = util::make_unique<Element>();
280ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        size_t len;
281ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const char16_t* str16 = tree.getElementNamespace(&len);
282ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
283ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
284ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        }
28575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
286ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        str16 = tree.getElementName(&len);
287ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
288ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          node->name = util::Utf16ToUtf8(StringPiece16(str16, len));
28975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
29075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
291ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        CopyAttributes(node.get(), &tree);
292ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
293ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        new_node = std::move(node);
294ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
295ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
296ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
297ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::TEXT: {
298ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        std::unique_ptr<Text> node = util::make_unique<Text>();
299ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        size_t len;
300ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        const char16_t* str16 = tree.getText(&len);
301ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (str16) {
302ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          node->text = util::Utf16ToUtf8(StringPiece16(str16, len));
30375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
304ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        new_node = std::move(node);
305ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
306ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
307ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
308ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::END_NAMESPACE:
309ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      case ResXMLParser::END_TAG:
310ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        CHECK(!node_stack.empty());
311ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        node_stack.pop();
312ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
313ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
314ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      default:
315ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        LOG(FATAL) << "unhandled XML chunk type";
316ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
31775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
31875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
319ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (new_node) {
320ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      new_node->line_number = tree.getLineNumber();
321ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
322ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      Node* this_node = new_node.get();
323ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!root) {
324ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        CHECK(node_stack.empty()) << "node stack should be empty";
325ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        root = std::move(new_node);
326ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      } else {
327ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        CHECK(!node_stack.empty()) << "node stack should not be empty";
328ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        node_stack.top()->AddChild(std::move(new_node));
329ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
330ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
331ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!NodeCast<Text>(this_node)) {
332ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        node_stack.push(this_node);
333ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
3345eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski    }
335ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
336ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return util::make_unique<XmlResource>(ResourceFile{}, std::move(root));
3375eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
3385eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
339ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<Node> Namespace::Clone() {
340ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  auto ns = util::make_unique<Namespace>();
341ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ns->comment = comment;
342ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ns->line_number = line_number;
343ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ns->column_number = column_number;
344ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ns->namespace_prefix = namespace_prefix;
345ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ns->namespace_uri = namespace_uri;
346ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
347ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  ns->children.reserve(children.size());
348ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const std::unique_ptr<xml::Node>& child : children) {
349ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    ns->AddChild(child->Clone());
350ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
351ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return std::move(ns);
352467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski}
353467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
354ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* FindRootElement(XmlResource* doc) {
355ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return FindRootElement(doc->root.get());
356ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}
357ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski
358ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* FindRootElement(Node* node) {
359ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!node) {
360ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return nullptr;
361ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
362ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
363ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Element* el = nullptr;
364ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  while ((el = NodeCast<Element>(node)) == nullptr) {
365ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (node->children.empty()) {
366ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return nullptr;
367ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski    }
368ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    // We are looking for the first element, and namespaces can only have one
369ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    // child.
370ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    node = node->children.front().get();
371ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
372ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return el;
373ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski}
374ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski
375ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskivoid Node::AddChild(std::unique_ptr<Node> child) {
376ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  child->parent = this;
377ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  children.push_back(std::move(child));
37875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
37975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
380ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiAttribute* Element::FindAttribute(const StringPiece& ns,
381ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                  const StringPiece& name) {
382ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (auto& attr : attributes) {
383ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (ns == attr.namespace_uri && name == attr.name) {
384ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return &attr;
38575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
386ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
387ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return nullptr;
38875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
38975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
390ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* Element::FindChild(const StringPiece& ns, const StringPiece& name) {
391ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return FindChildWithAttribute(ns, name, {}, {}, {});
39275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
39375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
394ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* Element::FindChildWithAttribute(const StringPiece& ns,
395ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                         const StringPiece& name,
396ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                         const StringPiece& attr_ns,
397ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                         const StringPiece& attr_name,
398ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                         const StringPiece& attr_value) {
399ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (auto& child_node : children) {
400ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    Node* child = child_node.get();
401ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    while (NodeCast<Namespace>(child)) {
402ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (child->children.empty()) {
403ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
404ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
405ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      child = child->children[0].get();
40675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
40775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
408ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (Element* el = NodeCast<Element>(child)) {
409ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (ns == el->namespace_uri && name == el->name) {
410ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (attr_ns.empty() && attr_name.empty()) {
411ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          return el;
41275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
41375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
414ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        Attribute* attr = el->FindAttribute(attr_ns, attr_name);
415ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (attr && attr_value == attr->value) {
416ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          return el;
41775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski        }
418ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
41975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski    }
420ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
421ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return nullptr;
42275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}
42375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski
424ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::vector<Element*> Element::GetChildElements() {
425ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  std::vector<Element*> elements;
426ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (auto& child_node : children) {
427ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    Node* child = child_node.get();
428ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    while (NodeCast<Namespace>(child)) {
429ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (child->children.empty()) {
430ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        break;
431ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
432ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      child = child->children[0].get();
4335eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski    }
4345eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
435ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (Element* el = NodeCast<Element>(child)) {
436ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      elements.push_back(el);
4375eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski    }
438ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
439ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return elements;
4405eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
4415eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
442ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<Node> Element::Clone() {
443ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  auto el = util::make_unique<Element>();
444ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->comment = comment;
445ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->line_number = line_number;
446ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->column_number = column_number;
447ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->name = name;
448ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->namespace_uri = namespace_uri;
449ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
450ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->attributes.reserve(attributes.size());
451ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (xml::Attribute& attr : attributes) {
452ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    // Don't copy compiled values or attributes.
453ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    el->attributes.push_back(
454ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        xml::Attribute{attr.namespace_uri, attr.name, attr.value});
455ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
456ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
457ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  el->children.reserve(children.size());
458ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const std::unique_ptr<xml::Node>& child : children) {
459ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    el->AddChild(child->Clone());
460ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
461ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return std::move(el);
4625eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski}
4635eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski
464ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<Node> Text::Clone() {
465ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  auto t = util::make_unique<Text>();
466ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->comment = comment;
467ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->line_number = line_number;
468ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->column_number = column_number;
469ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  t->text = text;
470ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return std::move(t);
471ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}
472467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
473ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskivoid PackageAwareVisitor::Visit(Namespace* ns) {
474ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool added = false;
475ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (Maybe<ExtractedPackage> maybe_package =
476ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          ExtractPackageFromNamespace(ns->namespace_uri)) {
477ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    ExtractedPackage& package = maybe_package.value();
478ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    package_decls_.push_back(
479ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        PackageDecl{ns->namespace_prefix, std::move(package)});
480ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    added = true;
481ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
482ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
483ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  Visitor::Visit(ns);
484ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
485ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (added) {
486ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    package_decls_.pop_back();
487ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
488467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski}
489467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
490ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiMaybe<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias(
491ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    const StringPiece& alias, const StringPiece& local_package) const {
492ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (alias.empty()) {
493ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    return ExtractedPackage{local_package.ToString(), false /* private */};
494ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
495ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
496ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const auto rend = package_decls_.rend();
497ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) {
498ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    if (alias == iter->prefix) {
499ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (iter->package.package.empty()) {
500ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        return ExtractedPackage{local_package.ToString(),
501ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski                                iter->package.private_namespace};
502ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      }
503ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      return iter->package;
504ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    }
505ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  }
506ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return {};
507467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski}
508467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
509ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}  // namespace xml
510ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski}  // namespace aapt
511