blob: 960d3614305e8b804db333f71e2a43d559052b4f [file] [log] [blame]
Adam Lesinski75f3a552015-06-03 14:54:23 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Adam Lesinski75f3a552015-06-03 14:54:23 -070017#include "XmlDom.h"
Adam Lesinskice5e56e2016-10-21 17:56:45 -070018
19#include <expat.h>
Adam Lesinski75f3a552015-06-03 14:54:23 -070020
21#include <cassert>
22#include <memory>
23#include <stack>
24#include <string>
25#include <tuple>
26
Adam Lesinskice5e56e2016-10-21 17:56:45 -070027#include "android-base/logging.h"
28
29#include "XmlPullParser.h"
30#include "util/Util.h"
31
Adam Lesinski75f3a552015-06-03 14:54:23 -070032namespace aapt {
33namespace xml {
34
35constexpr char kXmlNamespaceSep = 1;
36
37struct Stack {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070038 std::unique_ptr<xml::Node> root;
39 std::stack<xml::Node*> node_stack;
40 std::string pending_comment;
Adam Lesinski75f3a552015-06-03 14:54:23 -070041};
42
43/**
44 * Extracts the namespace and name of an expanded element or attribute name.
45 */
Adam Lesinskice5e56e2016-10-21 17:56:45 -070046static void SplitName(const char* name, std::string* out_ns,
47 std::string* out_name) {
48 const char* p = name;
49 while (*p != 0 && *p != kXmlNamespaceSep) {
50 p++;
51 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070052
Adam Lesinskice5e56e2016-10-21 17:56:45 -070053 if (*p == 0) {
54 out_ns->clear();
55 *out_name = StringPiece(name).ToString();
56 } else {
57 *out_ns = StringPiece(name, (p - name)).ToString();
58 *out_name = StringPiece(p + 1).ToString();
59 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070060}
61
Adam Lesinskice5e56e2016-10-21 17:56:45 -070062static void AddToStack(Stack* stack, XML_Parser parser,
63 std::unique_ptr<Node> node) {
64 node->line_number = XML_GetCurrentLineNumber(parser);
65 node->column_number = XML_GetCurrentColumnNumber(parser);
Adam Lesinski75f3a552015-06-03 14:54:23 -070066
Adam Lesinskice5e56e2016-10-21 17:56:45 -070067 Node* this_node = node.get();
68 if (!stack->node_stack.empty()) {
Adam Lesinskie343eb12016-10-27 16:31:58 -070069 stack->node_stack.top()->AppendChild(std::move(node));
Adam Lesinskice5e56e2016-10-21 17:56:45 -070070 } else {
71 stack->root = std::move(node);
72 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070073
Adam Lesinskice5e56e2016-10-21 17:56:45 -070074 if (!NodeCast<Text>(this_node)) {
75 stack->node_stack.push(this_node);
76 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070077}
78
Adam Lesinskice5e56e2016-10-21 17:56:45 -070079static void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix,
80 const char* uri) {
81 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
82 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinski75f3a552015-06-03 14:54:23 -070083
Adam Lesinskice5e56e2016-10-21 17:56:45 -070084 std::unique_ptr<Namespace> ns = util::make_unique<Namespace>();
85 if (prefix) {
86 ns->namespace_prefix = StringPiece(prefix).ToString();
87 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070088
Adam Lesinskice5e56e2016-10-21 17:56:45 -070089 if (uri) {
90 ns->namespace_uri = StringPiece(uri).ToString();
91 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070092
Adam Lesinskice5e56e2016-10-21 17:56:45 -070093 AddToStack(stack, parser, std::move(ns));
Adam Lesinski75f3a552015-06-03 14:54:23 -070094}
95
Adam Lesinskice5e56e2016-10-21 17:56:45 -070096static void XMLCALL EndNamespaceHandler(void* user_data, const char* prefix) {
97 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
98 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinski75f3a552015-06-03 14:54:23 -070099
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700100 CHECK(!stack->node_stack.empty());
101 stack->node_stack.pop();
Adam Lesinski75f3a552015-06-03 14:54:23 -0700102}
103
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700104static bool less_attribute(const Attribute& lhs, const Attribute& rhs) {
105 return std::tie(lhs.namespace_uri, lhs.name, lhs.value) <
106 std::tie(rhs.namespace_uri, rhs.name, rhs.value);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700107}
108
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700109static void XMLCALL StartElementHandler(void* user_data, const char* name,
110 const char** attrs) {
111 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
112 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700113
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700114 std::unique_ptr<Element> el = util::make_unique<Element>();
115 SplitName(name, &el->namespace_uri, &el->name);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700116
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700117 while (*attrs) {
118 Attribute attribute;
119 SplitName(*attrs++, &attribute.namespace_uri, &attribute.name);
120 attribute.value = StringPiece(*attrs++).ToString();
Adam Lesinski75f3a552015-06-03 14:54:23 -0700121
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700122 // Insert in sorted order.
123 auto iter = std::lower_bound(el->attributes.begin(), el->attributes.end(),
124 attribute, less_attribute);
125 el->attributes.insert(iter, std::move(attribute));
126 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700127
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700128 el->comment = std::move(stack->pending_comment);
129 AddToStack(stack, parser, std::move(el));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700130}
131
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700132static void XMLCALL EndElementHandler(void* user_data, const char* name) {
133 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
134 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700135
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700136 CHECK(!stack->node_stack.empty());
137 // stack->nodeStack.top()->comment = std::move(stack->pendingComment);
138 stack->node_stack.pop();
Adam Lesinski75f3a552015-06-03 14:54:23 -0700139}
140
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700141static void XMLCALL CharacterDataHandler(void* user_data, const char* s,
142 int len) {
143 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
144 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700145
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700146 if (!s || len <= 0) {
147 return;
148 }
149
150 // See if we can just append the text to a previous text node.
151 if (!stack->node_stack.empty()) {
152 Node* currentParent = stack->node_stack.top();
153 if (!currentParent->children.empty()) {
154 Node* last_child = currentParent->children.back().get();
155 if (Text* text = NodeCast<Text>(last_child)) {
156 text->text += StringPiece(s, len).ToString();
Adam Lesinski75f3a552015-06-03 14:54:23 -0700157 return;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700158 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700159 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700160 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700161
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700162 std::unique_ptr<Text> text = util::make_unique<Text>();
163 text->text = StringPiece(s, len).ToString();
164 AddToStack(stack, parser, std::move(text));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700165}
166
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700167static void XMLCALL CommentDataHandler(void* user_data, const char* comment) {
168 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
169 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700170
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700171 if (!stack->pending_comment.empty()) {
172 stack->pending_comment += '\n';
173 }
174 stack->pending_comment += comment;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700175}
176
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700177std::unique_ptr<XmlResource> Inflate(std::istream* in, IDiagnostics* diag,
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700178 const Source& source) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700179 Stack stack;
Adam Lesinski803c7c82016-04-06 16:09:43 -0700180
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700181 XML_Parser parser = XML_ParserCreateNS(nullptr, kXmlNamespaceSep);
182 XML_SetUserData(parser, &stack);
183 XML_UseParserAsHandlerArg(parser);
184 XML_SetElementHandler(parser, StartElementHandler, EndElementHandler);
185 XML_SetNamespaceDeclHandler(parser, StartNamespaceHandler,
186 EndNamespaceHandler);
187 XML_SetCharacterDataHandler(parser, CharacterDataHandler);
188 XML_SetCommentHandler(parser, CommentDataHandler);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700189
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700190 char buffer[1024];
191 while (!in->eof()) {
192 in->read(buffer, sizeof(buffer) / sizeof(buffer[0]));
193 if (in->bad() && !in->eof()) {
194 stack.root = {};
195 diag->Error(DiagMessage(source) << strerror(errno));
196 break;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700197 }
198
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700199 if (XML_Parse(parser, buffer, in->gcount(), in->eof()) ==
200 XML_STATUS_ERROR) {
201 stack.root = {};
202 diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser)))
203 << XML_ErrorString(XML_GetErrorCode(parser)));
204 break;
205 }
206 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700207
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700208 XML_ParserFree(parser);
209 if (stack.root) {
210 return util::make_unique<XmlResource>(ResourceFile{{}, {}, source},
211 std::move(stack.root));
212 }
213 return {};
214}
Adam Lesinski75f3a552015-06-03 14:54:23 -0700215
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700216static void CopyAttributes(Element* el, android::ResXMLParser* parser) {
217 const size_t attr_count = parser->getAttributeCount();
218 if (attr_count > 0) {
219 el->attributes.reserve(attr_count);
220 for (size_t i = 0; i < attr_count; i++) {
221 Attribute attr;
222 size_t len;
223 const char16_t* str16 = parser->getAttributeNamespace(i, &len);
224 if (str16) {
225 attr.namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
226 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700227
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700228 str16 = parser->getAttributeName(i, &len);
229 if (str16) {
230 attr.name = util::Utf16ToUtf8(StringPiece16(str16, len));
231 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700232
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700233 str16 = parser->getAttributeStringValue(i, &len);
234 if (str16) {
235 attr.value = util::Utf16ToUtf8(StringPiece16(str16, len));
236 }
237 el->attributes.push_back(std::move(attr));
238 }
239 }
240}
Adam Lesinski75f3a552015-06-03 14:54:23 -0700241
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700242std::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len,
243 IDiagnostics* diag, const Source& source) {
244 // We import the android namespace because on Windows NO_ERROR is a macro, not
245 // an enum, which
246 // causes errors when qualifying it with android::
247 using namespace android;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700248
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700249 std::unique_ptr<Node> root;
250 std::stack<Node*> node_stack;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700251
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700252 ResXMLTree tree;
253 if (tree.setTo(data, data_len) != NO_ERROR) {
254 return {};
255 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700256
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700257 ResXMLParser::event_code_t code;
258 while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT &&
259 code != ResXMLParser::END_DOCUMENT) {
260 std::unique_ptr<Node> new_node;
261 switch (code) {
262 case ResXMLParser::START_NAMESPACE: {
263 std::unique_ptr<Namespace> node = util::make_unique<Namespace>();
264 size_t len;
265 const char16_t* str16 = tree.getNamespacePrefix(&len);
266 if (str16) {
267 node->namespace_prefix = util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700268 }
269
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700270 str16 = tree.getNamespaceUri(&len);
271 if (str16) {
272 node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700273 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700274 new_node = std::move(node);
275 break;
276 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700277
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700278 case ResXMLParser::START_TAG: {
279 std::unique_ptr<Element> node = util::make_unique<Element>();
280 size_t len;
281 const char16_t* str16 = tree.getElementNamespace(&len);
282 if (str16) {
283 node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinskica5638f2015-10-21 14:42:43 -0700284 }
Adam Lesinskica5638f2015-10-21 14:42:43 -0700285
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700286 str16 = tree.getElementName(&len);
287 if (str16) {
288 node->name = util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700289 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700290
291 CopyAttributes(node.get(), &tree);
292
293 new_node = std::move(node);
294 break;
295 }
296
297 case ResXMLParser::TEXT: {
298 std::unique_ptr<Text> node = util::make_unique<Text>();
299 size_t len;
300 const char16_t* str16 = tree.getText(&len);
301 if (str16) {
302 node->text = util::Utf16ToUtf8(StringPiece16(str16, len));
303 }
304 new_node = std::move(node);
305 break;
306 }
307
308 case ResXMLParser::END_NAMESPACE:
309 case ResXMLParser::END_TAG:
310 CHECK(!node_stack.empty());
311 node_stack.pop();
312 break;
313
314 default:
315 LOG(FATAL) << "unhandled XML chunk type";
316 break;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700317 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700318
319 if (new_node) {
320 new_node->line_number = tree.getLineNumber();
321
322 Node* this_node = new_node.get();
323 if (!root) {
324 CHECK(node_stack.empty()) << "node stack should be empty";
325 root = std::move(new_node);
326 } else {
327 CHECK(!node_stack.empty()) << "node stack should not be empty";
Adam Lesinskie343eb12016-10-27 16:31:58 -0700328 node_stack.top()->AppendChild(std::move(new_node));
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700329 }
330
331 if (!NodeCast<Text>(this_node)) {
332 node_stack.push(this_node);
333 }
334 }
335 }
336 return util::make_unique<XmlResource>(ResourceFile{}, std::move(root));
337}
338
339std::unique_ptr<Node> Namespace::Clone() {
340 auto ns = util::make_unique<Namespace>();
341 ns->comment = comment;
342 ns->line_number = line_number;
343 ns->column_number = column_number;
344 ns->namespace_prefix = namespace_prefix;
345 ns->namespace_uri = namespace_uri;
346
347 ns->children.reserve(children.size());
348 for (const std::unique_ptr<xml::Node>& child : children) {
Adam Lesinskie343eb12016-10-27 16:31:58 -0700349 ns->AppendChild(child->Clone());
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700350 }
351 return std::move(ns);
352}
353
354Element* FindRootElement(XmlResource* doc) {
355 return FindRootElement(doc->root.get());
356}
357
358Element* FindRootElement(Node* node) {
359 if (!node) {
Adam Lesinski75f3a552015-06-03 14:54:23 -0700360 return nullptr;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700361 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700362
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700363 Element* el = nullptr;
364 while ((el = NodeCast<Element>(node)) == nullptr) {
365 if (node->children.empty()) {
366 return nullptr;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700367 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700368 // We are looking for the first element, and namespaces can only have one
369 // child.
370 node = node->children.front().get();
371 }
372 return el;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700373}
374
Adam Lesinskie343eb12016-10-27 16:31:58 -0700375void Node::AppendChild(std::unique_ptr<Node> child) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700376 child->parent = this;
377 children.push_back(std::move(child));
378}
Adam Lesinski75f3a552015-06-03 14:54:23 -0700379
Adam Lesinskie343eb12016-10-27 16:31:58 -0700380void Node::InsertChild(size_t index, std::unique_ptr<Node> child) {
381 child->parent = this;
382 children.insert(children.begin() + index, std::move(child));
383}
384
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700385Attribute* Element::FindAttribute(const StringPiece& ns,
386 const StringPiece& name) {
387 for (auto& attr : attributes) {
388 if (ns == attr.namespace_uri && name == attr.name) {
389 return &attr;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700390 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700391 }
392 return nullptr;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700393}
394
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700395Element* Element::FindChild(const StringPiece& ns, const StringPiece& name) {
396 return FindChildWithAttribute(ns, name, {}, {}, {});
397}
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700398
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700399Element* Element::FindChildWithAttribute(const StringPiece& ns,
400 const StringPiece& name,
401 const StringPiece& attr_ns,
402 const StringPiece& attr_name,
403 const StringPiece& attr_value) {
404 for (auto& child_node : children) {
405 Node* child = child_node.get();
406 while (NodeCast<Namespace>(child)) {
407 if (child->children.empty()) {
408 break;
409 }
410 child = child->children[0].get();
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700411 }
412
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700413 if (Element* el = NodeCast<Element>(child)) {
414 if (ns == el->namespace_uri && name == el->name) {
415 if (attr_ns.empty() && attr_name.empty()) {
416 return el;
417 }
418
419 Attribute* attr = el->FindAttribute(attr_ns, attr_name);
420 if (attr && attr_value == attr->value) {
421 return el;
422 }
423 }
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700424 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700425 }
426 return nullptr;
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700427}
428
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700429std::vector<Element*> Element::GetChildElements() {
430 std::vector<Element*> elements;
431 for (auto& child_node : children) {
432 Node* child = child_node.get();
433 while (NodeCast<Namespace>(child)) {
434 if (child->children.empty()) {
435 break;
436 }
437 child = child->children[0].get();
438 }
439
440 if (Element* el = NodeCast<Element>(child)) {
441 elements.push_back(el);
442 }
443 }
444 return elements;
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700445}
446
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700447std::unique_ptr<Node> Element::Clone() {
448 auto el = util::make_unique<Element>();
449 el->comment = comment;
450 el->line_number = line_number;
451 el->column_number = column_number;
452 el->name = name;
453 el->namespace_uri = namespace_uri;
Adam Lesinski467f1712015-11-16 17:35:44 -0800454
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700455 el->attributes.reserve(attributes.size());
456 for (xml::Attribute& attr : attributes) {
457 // Don't copy compiled values or attributes.
458 el->attributes.push_back(
459 xml::Attribute{attr.namespace_uri, attr.name, attr.value});
460 }
Adam Lesinski467f1712015-11-16 17:35:44 -0800461
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700462 el->children.reserve(children.size());
463 for (const std::unique_ptr<xml::Node>& child : children) {
Adam Lesinskie343eb12016-10-27 16:31:58 -0700464 el->AppendChild(child->Clone());
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700465 }
466 return std::move(el);
Adam Lesinski467f1712015-11-16 17:35:44 -0800467}
468
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700469std::unique_ptr<Node> Text::Clone() {
470 auto t = util::make_unique<Text>();
471 t->comment = comment;
472 t->line_number = line_number;
473 t->column_number = column_number;
474 t->text = text;
475 return std::move(t);
Adam Lesinski467f1712015-11-16 17:35:44 -0800476}
477
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700478void PackageAwareVisitor::Visit(Namespace* ns) {
479 bool added = false;
480 if (Maybe<ExtractedPackage> maybe_package =
481 ExtractPackageFromNamespace(ns->namespace_uri)) {
482 ExtractedPackage& package = maybe_package.value();
483 package_decls_.push_back(
484 PackageDecl{ns->namespace_prefix, std::move(package)});
485 added = true;
486 }
487
488 Visitor::Visit(ns);
489
490 if (added) {
491 package_decls_.pop_back();
492 }
493}
494
495Maybe<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias(
496 const StringPiece& alias, const StringPiece& local_package) const {
497 if (alias.empty()) {
498 return ExtractedPackage{local_package.ToString(), false /* private */};
499 }
500
501 const auto rend = package_decls_.rend();
502 for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) {
503 if (alias == iter->prefix) {
504 if (iter->package.package.empty()) {
505 return ExtractedPackage{local_package.ToString(),
506 iter->package.private_namespace};
507 }
508 return iter->package;
509 }
510 }
511 return {};
512}
513
514} // namespace xml
515} // namespace aapt