blob: f51e8a47041d20b5725b9a00e3a7b799efc3301e [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
Adam Lesinski75f3a552015-06-03 14:54:23 -070021#include <memory>
22#include <stack>
23#include <string>
24#include <tuple>
25
Adam Lesinskice5e56e2016-10-21 17:56:45 -070026#include "android-base/logging.h"
27
Adam Lesinskid0f492d2017-04-03 18:12:45 -070028#include "ResourceUtils.h"
Fabien Sanglard2d34e762019-02-21 15:13:29 -080029#include "trace/TraceBuffer.h"
Adam Lesinskice5e56e2016-10-21 17:56:45 -070030#include "XmlPullParser.h"
31#include "util/Util.h"
32
Adam Lesinskiefeb7af2017-08-02 14:57:43 -070033using ::aapt::io::InputStream;
34using ::android::StringPiece;
35using ::android::StringPiece16;
Adam Lesinskid5083f62017-01-16 15:07:21 -080036
Adam Lesinski75f3a552015-06-03 14:54:23 -070037namespace aapt {
38namespace xml {
39
40constexpr char kXmlNamespaceSep = 1;
41
42struct Stack {
Adam Lesinski6b372992017-08-09 10:54:23 -070043 std::unique_ptr<xml::Element> root;
44 std::stack<xml::Element*> node_stack;
45 std::unique_ptr<xml::Element> pending_element;
Adam Lesinskice5e56e2016-10-21 17:56:45 -070046 std::string pending_comment;
Adam Lesinskiac6edc52017-03-02 19:31:28 -080047 std::unique_ptr<xml::Text> last_text_node;
Adam Lesinski75f3a552015-06-03 14:54:23 -070048};
49
Adam Lesinski6b372992017-08-09 10:54:23 -070050// Extracts the namespace and name of an expanded element or attribute name.
51static void SplitName(const char* name, std::string* out_ns, std::string* out_name) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070052 const char* p = name;
53 while (*p != 0 && *p != kXmlNamespaceSep) {
54 p++;
55 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070056
Adam Lesinskice5e56e2016-10-21 17:56:45 -070057 if (*p == 0) {
58 out_ns->clear();
Adam Lesinskid5083f62017-01-16 15:07:21 -080059 out_name->assign(name);
Adam Lesinskice5e56e2016-10-21 17:56:45 -070060 } else {
Adam Lesinskid5083f62017-01-16 15:07:21 -080061 out_ns->assign(name, (p - name));
62 out_name->assign(p + 1);
Adam Lesinskice5e56e2016-10-21 17:56:45 -070063 }
Adam Lesinski75f3a552015-06-03 14:54:23 -070064}
65
Adam Lesinskiac6edc52017-03-02 19:31:28 -080066static void FinishPendingText(Stack* stack) {
67 if (stack->last_text_node != nullptr) {
Adam Lesinski48448e82017-04-26 15:13:52 -070068 if (!stack->last_text_node->text.empty()) {
Adam Lesinski6b372992017-08-09 10:54:23 -070069 CHECK(!stack->node_stack.empty());
Adam Lesinskiac6edc52017-03-02 19:31:28 -080070 stack->node_stack.top()->AppendChild(std::move(stack->last_text_node));
71 } else {
72 // Drop an empty text node.
Adam Lesinskiac6edc52017-03-02 19:31:28 -080073 }
Adam Lesinski48448e82017-04-26 15:13:52 -070074 stack->last_text_node = nullptr;
Adam Lesinskiac6edc52017-03-02 19:31:28 -080075 }
76}
77
Adam Lesinski6b372992017-08-09 10:54:23 -070078static void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix, const char* uri) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070079 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
80 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinskiac6edc52017-03-02 19:31:28 -080081 FinishPendingText(stack);
Adam Lesinski75f3a552015-06-03 14:54:23 -070082
Adam Lesinski6b372992017-08-09 10:54:23 -070083 NamespaceDecl decl;
84 decl.line_number = XML_GetCurrentLineNumber(parser);
85 decl.column_number = XML_GetCurrentColumnNumber(parser);
86 decl.prefix = prefix ? prefix : "";
87 decl.uri = uri ? uri : "";
Adam Lesinski75f3a552015-06-03 14:54:23 -070088
Adam Lesinski6b372992017-08-09 10:54:23 -070089 if (stack->pending_element == nullptr) {
90 stack->pending_element = util::make_unique<Element>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -070091 }
Adam Lesinski6b372992017-08-09 10:54:23 -070092 stack->pending_element->namespace_decls.push_back(std::move(decl));
Adam Lesinski75f3a552015-06-03 14:54:23 -070093}
94
Adam Lesinski6b372992017-08-09 10:54:23 -070095static void XMLCALL EndNamespaceHandler(void* user_data, const char* /*prefix*/) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070096 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
97 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinskiac6edc52017-03-02 19:31:28 -080098 FinishPendingText(stack);
Adam Lesinski75f3a552015-06-03 14:54:23 -070099}
100
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700101static bool less_attribute(const Attribute& lhs, const Attribute& rhs) {
102 return std::tie(lhs.namespace_uri, lhs.name, lhs.value) <
103 std::tie(rhs.namespace_uri, rhs.name, rhs.value);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700104}
105
Adam Lesinski6b372992017-08-09 10:54:23 -0700106static void XMLCALL StartElementHandler(void* user_data, const char* name, const char** attrs) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700107 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
108 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinskiac6edc52017-03-02 19:31:28 -0800109 FinishPendingText(stack);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700110
Adam Lesinski6b372992017-08-09 10:54:23 -0700111 std::unique_ptr<Element> el;
112 if (stack->pending_element != nullptr) {
113 el = std::move(stack->pending_element);
114 } else {
115 el = util::make_unique<Element>();
116 }
117
118 el->line_number = XML_GetCurrentLineNumber(parser);
119 el->column_number = XML_GetCurrentColumnNumber(parser);
120 el->comment = std::move(stack->pending_comment);
121
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700122 SplitName(name, &el->namespace_uri, &el->name);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700123
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700124 while (*attrs) {
125 Attribute attribute;
126 SplitName(*attrs++, &attribute.namespace_uri, &attribute.name);
Adam Lesinski48448e82017-04-26 15:13:52 -0700127 attribute.value = *attrs++;
Adam Lesinski6b372992017-08-09 10:54:23 -0700128 el->attributes.push_back(std::move(attribute));
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700129 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700130
Adam Lesinski6b372992017-08-09 10:54:23 -0700131 // Sort the attributes.
132 std::sort(el->attributes.begin(), el->attributes.end(), less_attribute);
133
134 // Add to the stack.
135 Element* this_el = el.get();
136 if (!stack->node_stack.empty()) {
137 stack->node_stack.top()->AppendChild(std::move(el));
138 } else {
139 stack->root = std::move(el);
140 }
141 stack->node_stack.push(this_el);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700142}
143
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700144static void XMLCALL EndElementHandler(void* user_data, const char* name) {
145 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
146 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinskiac6edc52017-03-02 19:31:28 -0800147 FinishPendingText(stack);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700148
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700149 CHECK(!stack->node_stack.empty());
150 // stack->nodeStack.top()->comment = std::move(stack->pendingComment);
151 stack->node_stack.pop();
Adam Lesinski75f3a552015-06-03 14:54:23 -0700152}
153
Adam Lesinskiac6edc52017-03-02 19:31:28 -0800154static void XMLCALL CharacterDataHandler(void* user_data, const char* s, int len) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700155 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
156 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700157
Adam Lesinskiac6edc52017-03-02 19:31:28 -0800158 const StringPiece str(s, len);
159 if (str.empty()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700160 return;
161 }
162
163 // See if we can just append the text to a previous text node.
Adam Lesinskiac6edc52017-03-02 19:31:28 -0800164 if (stack->last_text_node != nullptr) {
Adam Lesinski48448e82017-04-26 15:13:52 -0700165 stack->last_text_node->text.append(str.data(), str.size());
Adam Lesinskiac6edc52017-03-02 19:31:28 -0800166 return;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700167 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700168
Adam Lesinskiac6edc52017-03-02 19:31:28 -0800169 stack->last_text_node = util::make_unique<Text>();
170 stack->last_text_node->line_number = XML_GetCurrentLineNumber(parser);
171 stack->last_text_node->column_number = XML_GetCurrentColumnNumber(parser);
Adam Lesinski48448e82017-04-26 15:13:52 -0700172 stack->last_text_node->text = str.to_string();
Adam Lesinski75f3a552015-06-03 14:54:23 -0700173}
174
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700175static void XMLCALL CommentDataHandler(void* user_data, const char* comment) {
176 XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
177 Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
Adam Lesinskiac6edc52017-03-02 19:31:28 -0800178 FinishPendingText(stack);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700179
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700180 if (!stack->pending_comment.empty()) {
181 stack->pending_comment += '\n';
182 }
183 stack->pending_comment += comment;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700184}
185
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000186std::unique_ptr<XmlResource> Inflate(InputStream* in, android::IDiagnostics* diag,
187 const android::Source& source) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700188 Stack stack;
Adam Lesinski803c7c82016-04-06 16:09:43 -0700189
Adam Lesinskiefeb7af2017-08-02 14:57:43 -0700190 std::unique_ptr<std::remove_pointer<XML_Parser>::type, decltype(XML_ParserFree)*> parser = {
191 XML_ParserCreateNS(nullptr, kXmlNamespaceSep), XML_ParserFree};
192 XML_SetUserData(parser.get(), &stack);
193 XML_UseParserAsHandlerArg(parser.get());
194 XML_SetElementHandler(parser.get(), StartElementHandler, EndElementHandler);
195 XML_SetNamespaceDeclHandler(parser.get(), StartNamespaceHandler, EndNamespaceHandler);
196 XML_SetCharacterDataHandler(parser.get(), CharacterDataHandler);
197 XML_SetCommentHandler(parser.get(), CommentDataHandler);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700198
Adam Lesinskiefeb7af2017-08-02 14:57:43 -0700199 const char* buffer = nullptr;
200 size_t buffer_size = 0;
201 while (in->Next(reinterpret_cast<const void**>(&buffer), &buffer_size)) {
202 if (XML_Parse(parser.get(), buffer, buffer_size, false) == XML_STATUS_ERROR) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000203 diag->Error(android::DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser.get())))
Adam Lesinskiefeb7af2017-08-02 14:57:43 -0700204 << XML_ErrorString(XML_GetErrorCode(parser.get())));
205 return {};
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700206 }
207 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700208
Adam Lesinskiefeb7af2017-08-02 14:57:43 -0700209 if (in->HadError()) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000210 diag->Error(android::DiagMessage(source) << in->GetError());
Adam Lesinskiefeb7af2017-08-02 14:57:43 -0700211 return {};
212 } else {
213 // Finish off the parsing.
214 if (XML_Parse(parser.get(), nullptr, 0u, true) == XML_STATUS_ERROR) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000215 diag->Error(android::DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser.get())))
Adam Lesinskiefeb7af2017-08-02 14:57:43 -0700216 << XML_ErrorString(XML_GetErrorCode(parser.get())));
217 return {};
218 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700219 }
Adam Lesinski00451162017-10-03 07:44:08 -0700220 return util::make_unique<XmlResource>(ResourceFile{{}, {}, ResourceFile::Type::kUnknown, source},
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000221 android::StringPool{}, std::move(stack.root));
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700222}
Adam Lesinski75f3a552015-06-03 14:54:23 -0700223
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000224static void CopyAttributes(Element* el, android::ResXMLParser* parser,
225 android::StringPool* out_pool) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700226 const size_t attr_count = parser->getAttributeCount();
227 if (attr_count > 0) {
228 el->attributes.reserve(attr_count);
229 for (size_t i = 0; i < attr_count; i++) {
230 Attribute attr;
231 size_t len;
232 const char16_t* str16 = parser->getAttributeNamespace(i, &len);
233 if (str16) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000234 attr.namespace_uri = android::util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700235 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700236
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700237 str16 = parser->getAttributeName(i, &len);
238 if (str16) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000239 attr.name = android::util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700240 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700241
Shane Farmer4b8ca8b2017-09-08 12:17:05 -0700242 uint32_t res_id = parser->getAttributeNameResID(i);
243 if (res_id > 0) {
244 attr.compiled_attribute = AaptAttribute(::aapt::Attribute(), {res_id});
245 }
246
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700247 str16 = parser->getAttributeStringValue(i, &len);
248 if (str16) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000249 attr.value = android::util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700250 }
Adam Lesinskid0f492d2017-04-03 18:12:45 -0700251
Adam Lesinskibbf42972018-02-14 13:36:09 -0800252 android::Res_value res_value;
253 if (parser->getAttributeValue(i, &res_value) > 0) {
Adam Lesinskie1094a22018-02-22 17:27:17 -0800254 // Only compile the value if it is not a string, or it is a string that differs from
255 // the raw attribute value.
256 int32_t raw_value_idx = parser->getAttributeValueStringID(i);
257 if (res_value.dataType != android::Res_value::TYPE_STRING || raw_value_idx < 0 ||
258 static_cast<uint32_t>(raw_value_idx) != res_value.data) {
259 attr.compiled_value = ResourceUtils::ParseBinaryResValue(
260 ResourceType::kAnim, {}, parser->getStrings(), res_value, out_pool);
261 }
Adam Lesinskibbf42972018-02-14 13:36:09 -0800262 }
Adam Lesinskid0f492d2017-04-03 18:12:45 -0700263
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700264 el->attributes.push_back(std::move(attr));
265 }
266 }
267}
Adam Lesinski75f3a552015-06-03 14:54:23 -0700268
Adam Lesinski8780eb62017-10-31 17:44:39 -0700269std::unique_ptr<XmlResource> Inflate(const void* data, size_t len, std::string* out_error) {
Fabien Sanglard2d34e762019-02-21 15:13:29 -0800270 TRACE_CALL();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700271 // We import the android namespace because on Windows NO_ERROR is a macro, not
Adam Lesinski6b372992017-08-09 10:54:23 -0700272 // an enum, which causes errors when qualifying it with android::
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700273 using namespace android;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700274
Adam Lesinskie1094a22018-02-22 17:27:17 -0800275 std::unique_ptr<XmlResource> xml_resource = util::make_unique<XmlResource>();
276
Adam Lesinski6b372992017-08-09 10:54:23 -0700277 std::stack<Element*> node_stack;
278 std::unique_ptr<Element> pending_element;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700279
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700280 ResXMLTree tree;
Adam Lesinski8780eb62017-10-31 17:44:39 -0700281 if (tree.setTo(data, len) != NO_ERROR) {
282 if (out_error != nullptr) {
283 *out_error = "failed to initialize ResXMLTree";
284 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700285 return {};
286 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700287
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700288 ResXMLParser::event_code_t code;
Adam Lesinski6b372992017-08-09 10:54:23 -0700289 while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT && code != ResXMLParser::END_DOCUMENT) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700290 std::unique_ptr<Node> new_node;
291 switch (code) {
292 case ResXMLParser::START_NAMESPACE: {
Adam Lesinski6b372992017-08-09 10:54:23 -0700293 NamespaceDecl decl;
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700294 decl.line_number = tree.getLineNumber();
295
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700296 size_t len;
297 const char16_t* str16 = tree.getNamespacePrefix(&len);
298 if (str16) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000299 decl.prefix = android::util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700300 }
301
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700302 str16 = tree.getNamespaceUri(&len);
303 if (str16) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000304 decl.uri = android::util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700305 }
Adam Lesinski6b372992017-08-09 10:54:23 -0700306
307 if (pending_element == nullptr) {
308 pending_element = util::make_unique<Element>();
309 }
Chih-Hung Hsieh7a616f62020-03-05 15:59:25 -0800310 // pending_element is not nullptr
311 // NOLINTNEXTLINE(bugprone-use-after-move)
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700312 pending_element->namespace_decls.push_back(std::move(decl));
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700313 break;
314 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700315
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700316 case ResXMLParser::START_TAG: {
Adam Lesinski6b372992017-08-09 10:54:23 -0700317 std::unique_ptr<Element> el;
318 if (pending_element != nullptr) {
319 el = std::move(pending_element);
320 } else {
321 el = util::make_unique<Element>();
Adam Lesinski6b372992017-08-09 10:54:23 -0700322 }
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700323 el->line_number = tree.getLineNumber();
Adam Lesinski6b372992017-08-09 10:54:23 -0700324
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700325 size_t len;
326 const char16_t* str16 = tree.getElementNamespace(&len);
327 if (str16) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000328 el->namespace_uri = android::util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinskica5638f2015-10-21 14:42:43 -0700329 }
Adam Lesinskica5638f2015-10-21 14:42:43 -0700330
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700331 str16 = tree.getElementName(&len);
332 if (str16) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000333 el->name = android::util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700334 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700335
Adam Lesinski6b372992017-08-09 10:54:23 -0700336 Element* this_el = el.get();
Adam Lesinskie1094a22018-02-22 17:27:17 -0800337 CopyAttributes(el.get(), &tree, &xml_resource->string_pool);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700338
Adam Lesinski6b372992017-08-09 10:54:23 -0700339 if (!node_stack.empty()) {
340 node_stack.top()->AppendChild(std::move(el));
341 } else {
Adam Lesinskie1094a22018-02-22 17:27:17 -0800342 xml_resource->root = std::move(el);
Adam Lesinski6b372992017-08-09 10:54:23 -0700343 }
344 node_stack.push(this_el);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700345 break;
346 }
347
348 case ResXMLParser::TEXT: {
Adam Lesinski6b372992017-08-09 10:54:23 -0700349 std::unique_ptr<Text> text = util::make_unique<Text>();
350 text->line_number = tree.getLineNumber();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700351 size_t len;
352 const char16_t* str16 = tree.getText(&len);
353 if (str16) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000354 text->text = android::util::Utf16ToUtf8(StringPiece16(str16, len));
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700355 }
Adam Lesinski6b372992017-08-09 10:54:23 -0700356 CHECK(!node_stack.empty());
357 node_stack.top()->AppendChild(std::move(text));
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700358 break;
359 }
360
361 case ResXMLParser::END_NAMESPACE:
Adam Lesinski6b372992017-08-09 10:54:23 -0700362 break;
363
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700364 case ResXMLParser::END_TAG:
365 CHECK(!node_stack.empty());
366 node_stack.pop();
367 break;
368
369 default:
370 LOG(FATAL) << "unhandled XML chunk type";
371 break;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700372 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700373 }
Adam Lesinskie1094a22018-02-22 17:27:17 -0800374 return xml_resource;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700375}
376
Adam Lesinski8780eb62017-10-31 17:44:39 -0700377std::unique_ptr<XmlResource> XmlResource::Clone() const {
378 std::unique_ptr<XmlResource> cloned = util::make_unique<XmlResource>(file);
Ryan Mitchellefcdb952021-04-14 17:31:37 -0700379 CloningValueTransformer cloner(&cloned->string_pool);
Adam Lesinski8780eb62017-10-31 17:44:39 -0700380 if (root != nullptr) {
381 cloned->root = root->CloneElement([&](const xml::Element& src, xml::Element* dst) {
382 dst->attributes.reserve(src.attributes.size());
383 for (const xml::Attribute& attr : src.attributes) {
384 xml::Attribute cloned_attr;
385 cloned_attr.name = attr.name;
386 cloned_attr.namespace_uri = attr.namespace_uri;
387 cloned_attr.value = attr.value;
388 cloned_attr.compiled_attribute = attr.compiled_attribute;
389 if (attr.compiled_value != nullptr) {
Ryan Mitchellefcdb952021-04-14 17:31:37 -0700390 cloned_attr.compiled_value = attr.compiled_value->Transform(cloner);
Adam Lesinski8780eb62017-10-31 17:44:39 -0700391 }
392 dst->attributes.push_back(std::move(cloned_attr));
393 }
394 });
395 }
396 return cloned;
397}
398
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700399Element* FindRootElement(Node* node) {
Adam Lesinski6b372992017-08-09 10:54:23 -0700400 if (node == nullptr) {
Adam Lesinski75f3a552015-06-03 14:54:23 -0700401 return nullptr;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700402 }
Adam Lesinski75f3a552015-06-03 14:54:23 -0700403
Adam Lesinski6b372992017-08-09 10:54:23 -0700404 while (node->parent != nullptr) {
405 node = node->parent;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700406 }
Adam Lesinski6b372992017-08-09 10:54:23 -0700407 return NodeCast<Element>(node);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700408}
409
Adam Lesinski6b372992017-08-09 10:54:23 -0700410void Element::AppendChild(std::unique_ptr<Node> child) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700411 child->parent = this;
412 children.push_back(std::move(child));
413}
Adam Lesinski75f3a552015-06-03 14:54:23 -0700414
Adam Lesinski6b372992017-08-09 10:54:23 -0700415void Element::InsertChild(size_t index, std::unique_ptr<Node> child) {
Adam Lesinskie343eb12016-10-27 16:31:58 -0700416 child->parent = this;
417 children.insert(children.begin() + index, std::move(child));
418}
419
Adam Lesinski6b372992017-08-09 10:54:23 -0700420Attribute* Element::FindAttribute(const StringPiece& ns, const StringPiece& name) {
Adam Lesinski8780eb62017-10-31 17:44:39 -0700421 return const_cast<Attribute*>(static_cast<const Element*>(this)->FindAttribute(ns, name));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700422}
423
Adam Lesinskic744ae82017-05-17 19:28:38 -0700424const Attribute* Element::FindAttribute(const StringPiece& ns, const StringPiece& name) const {
425 for (const auto& attr : attributes) {
426 if (ns == attr.namespace_uri && name == attr.name) {
427 return &attr;
428 }
429 }
430 return nullptr;
431}
432
Colin Crossdcd58c42018-05-25 22:46:35 -0700433void Element::RemoveAttribute(const StringPiece& ns, const StringPiece& name) {
434 auto new_attr_end = std::remove_if(attributes.begin(), attributes.end(),
435 [&](const Attribute& attr) -> bool {
436 return ns == attr.namespace_uri && name == attr.name;
437 });
438
439 attributes.erase(new_attr_end, attributes.end());
440}
441
Adam Lesinskic6284372017-12-04 13:46:23 -0800442Attribute* Element::FindOrCreateAttribute(const StringPiece& ns, const StringPiece& name) {
443 Attribute* attr = FindAttribute(ns, name);
444 if (attr == nullptr) {
445 attributes.push_back(Attribute{ns.to_string(), name.to_string()});
446 attr = &attributes.back();
447 }
448 return attr;
449}
450
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700451Element* Element::FindChild(const StringPiece& ns, const StringPiece& name) {
452 return FindChildWithAttribute(ns, name, {}, {}, {});
453}
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700454
Adam Lesinski8780eb62017-10-31 17:44:39 -0700455const Element* Element::FindChild(const StringPiece& ns, const StringPiece& name) const {
456 return FindChildWithAttribute(ns, name, {}, {}, {});
457}
458
Adam Lesinski6b372992017-08-09 10:54:23 -0700459Element* Element::FindChildWithAttribute(const StringPiece& ns, const StringPiece& name,
460 const StringPiece& attr_ns, const StringPiece& attr_name,
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700461 const StringPiece& attr_value) {
Adam Lesinski8780eb62017-10-31 17:44:39 -0700462 return const_cast<Element*>(static_cast<const Element*>(this)->FindChildWithAttribute(
463 ns, name, attr_ns, attr_name, attr_value));
464}
465
466const Element* Element::FindChildWithAttribute(const StringPiece& ns, const StringPiece& name,
467 const StringPiece& attr_ns,
468 const StringPiece& attr_name,
469 const StringPiece& attr_value) const {
470 for (const auto& child : children) {
471 if (const Element* el = NodeCast<Element>(child.get())) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700472 if (ns == el->namespace_uri && name == el->name) {
473 if (attr_ns.empty() && attr_name.empty()) {
474 return el;
475 }
476
Adam Lesinski8780eb62017-10-31 17:44:39 -0700477 const Attribute* attr = el->FindAttribute(attr_ns, attr_name);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700478 if (attr && attr_value == attr->value) {
479 return el;
480 }
481 }
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700482 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700483 }
484 return nullptr;
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700485}
486
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700487std::vector<Element*> Element::GetChildElements() {
488 std::vector<Element*> elements;
489 for (auto& child_node : children) {
Adam Lesinski6b372992017-08-09 10:54:23 -0700490 if (Element* child = NodeCast<Element>(child_node.get())) {
491 elements.push_back(child);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700492 }
493 }
494 return elements;
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700495}
496
Adam Lesinski6b372992017-08-09 10:54:23 -0700497std::unique_ptr<Node> Element::Clone(const ElementCloneFunc& el_cloner) const {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700498 auto el = util::make_unique<Element>();
Adam Lesinski6b372992017-08-09 10:54:23 -0700499 el->namespace_decls = namespace_decls;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700500 el->comment = comment;
501 el->line_number = line_number;
502 el->column_number = column_number;
503 el->name = name;
504 el->namespace_uri = namespace_uri;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700505 el->attributes.reserve(attributes.size());
Adam Lesinskic744ae82017-05-17 19:28:38 -0700506 el_cloner(*this, el.get());
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700507 el->children.reserve(children.size());
508 for (const std::unique_ptr<xml::Node>& child : children) {
Adam Lesinskic744ae82017-05-17 19:28:38 -0700509 el->AppendChild(child->Clone(el_cloner));
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700510 }
511 return std::move(el);
Adam Lesinski467f1712015-11-16 17:35:44 -0800512}
513
Adam Lesinski6b372992017-08-09 10:54:23 -0700514std::unique_ptr<Element> Element::CloneElement(const ElementCloneFunc& el_cloner) const {
515 return std::unique_ptr<Element>(static_cast<Element*>(Clone(el_cloner).release()));
516}
517
518void Element::Accept(Visitor* visitor) {
519 visitor->BeforeVisitElement(this);
520 visitor->Visit(this);
521 visitor->AfterVisitElement(this);
522}
523
Adam Lesinskid3ffa8442017-09-28 13:34:35 -0700524void Element::Accept(ConstVisitor* visitor) const {
525 visitor->BeforeVisitElement(this);
526 visitor->Visit(this);
527 visitor->AfterVisitElement(this);
528}
529
Adam Lesinski6b372992017-08-09 10:54:23 -0700530std::unique_ptr<Node> Text::Clone(const ElementCloneFunc&) const {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700531 auto t = util::make_unique<Text>();
532 t->comment = comment;
533 t->line_number = line_number;
534 t->column_number = column_number;
535 t->text = text;
536 return std::move(t);
Adam Lesinski467f1712015-11-16 17:35:44 -0800537}
538
Adam Lesinski6b372992017-08-09 10:54:23 -0700539void Text::Accept(Visitor* visitor) {
540 visitor->Visit(this);
541}
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700542
Adam Lesinskid3ffa8442017-09-28 13:34:35 -0700543void Text::Accept(ConstVisitor* visitor) const {
544 visitor->Visit(this);
545}
546
Adam Lesinski6b372992017-08-09 10:54:23 -0700547void PackageAwareVisitor::BeforeVisitElement(Element* el) {
548 std::vector<PackageDecl> decls;
549 for (const NamespaceDecl& decl : el->namespace_decls) {
Ryan Mitchell4382e442021-07-14 12:53:01 -0700550 if (std::optional<ExtractedPackage> maybe_package = ExtractPackageFromNamespace(decl.uri)) {
Adam Lesinski6b372992017-08-09 10:54:23 -0700551 decls.push_back(PackageDecl{decl.prefix, std::move(maybe_package.value())});
552 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700553 }
Adam Lesinski6b372992017-08-09 10:54:23 -0700554 package_decls_.push_back(std::move(decls));
555}
556
557void PackageAwareVisitor::AfterVisitElement(Element* el) {
558 package_decls_.pop_back();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700559}
560
Ryan Mitchell4382e442021-07-14 12:53:01 -0700561std::optional<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias(
562 const StringPiece& alias) const {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700563 if (alias.empty()) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700564 return ExtractedPackage{{}, false /*private*/};
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700565 }
566
567 const auto rend = package_decls_.rend();
568 for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) {
Adam Lesinski6b372992017-08-09 10:54:23 -0700569 const std::vector<PackageDecl>& decls = *iter;
570 const auto rend2 = decls.rend();
571 for (auto iter2 = decls.rbegin(); iter2 != rend2; ++iter2) {
572 const PackageDecl& decl = *iter2;
573 if (alias == decl.prefix) {
574 if (decl.package.package.empty()) {
Adam Lesinski1ef0fa92017-08-15 21:32:49 -0700575 return ExtractedPackage{{}, decl.package.private_namespace};
Adam Lesinski6b372992017-08-09 10:54:23 -0700576 }
577 return decl.package;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700578 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700579 }
580 }
581 return {};
582}
583
584} // namespace xml
585} // namespace aapt