175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/* 275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Copyright (C) 2015 The Android Open Source Project 375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * 475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * you may not use this file except in compliance with the License. 675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * You may obtain a copy of the License at 775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * 875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * 1075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Unless required by applicable law or agreed to in writing, software 1175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 1275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * See the License for the specific language governing permissions and 1475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * limitations under the License. 1575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */ 1675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 1775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include "XmlDom.h" 1875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 19467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include <expat.h> 20ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 2175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <memory> 2275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <stack> 2375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <string> 2475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <tuple> 2575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 26ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "android-base/logging.h" 27ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 28d0f492db038c6210c1138865d816bfb134376538Adam Lesinski#include "ResourceUtils.h" 29ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "XmlPullParser.h" 30ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "util/Util.h" 31ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 32efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinskiusing ::aapt::io::InputStream; 33efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinskiusing ::android::StringPiece; 34efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinskiusing ::android::StringPiece16; 35d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski 3675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace aapt { 3775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace xml { 3875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 3975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskiconstexpr char kXmlNamespaceSep = 1; 4075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 4175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistruct Stack { 426b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski std::unique_ptr<xml::Element> root; 436b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski std::stack<xml::Element*> node_stack; 446b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski std::unique_ptr<xml::Element> pending_element; 45ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string pending_comment; 46ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski std::unique_ptr<xml::Text> last_text_node; 4775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}; 4875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 496b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski// Extracts the namespace and name of an expanded element or attribute name. 506b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistatic void SplitName(const char* name, std::string* out_ns, std::string* out_name) { 51ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char* p = name; 52ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while (*p != 0 && *p != kXmlNamespaceSep) { 53ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski p++; 54ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 55ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 56ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (*p == 0) { 57ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski out_ns->clear(); 58d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski out_name->assign(name); 59ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else { 60d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski out_ns->assign(name, (p - name)); 61d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski out_name->assign(p + 1); 62ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 6375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 6475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 65ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinskistatic void FinishPendingText(Stack* stack) { 66ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski if (stack->last_text_node != nullptr) { 6748448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski if (!stack->last_text_node->text.empty()) { 686b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski CHECK(!stack->node_stack.empty()); 69ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski stack->node_stack.top()->AppendChild(std::move(stack->last_text_node)); 70ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski } else { 71ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski // Drop an empty text node. 72ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski } 7348448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski stack->last_text_node = nullptr; 74ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski } 75ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski} 76ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski 776b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistatic void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix, const char* uri) { 78ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 80ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski FinishPendingText(stack); 8175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 826b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski NamespaceDecl decl; 836b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski decl.line_number = XML_GetCurrentLineNumber(parser); 846b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski decl.column_number = XML_GetCurrentColumnNumber(parser); 856b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski decl.prefix = prefix ? prefix : ""; 866b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski decl.uri = uri ? uri : ""; 8775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 886b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski if (stack->pending_element == nullptr) { 896b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski stack->pending_element = util::make_unique<Element>(); 90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 916b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski stack->pending_element->namespace_decls.push_back(std::move(decl)); 9275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 9375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 946b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistatic void XMLCALL EndNamespaceHandler(void* user_data, const char* /*prefix*/) { 95ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 96ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 97ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski FinishPendingText(stack); 9875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 9975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 100ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic bool less_attribute(const Attribute& lhs, const Attribute& rhs) { 101ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return std::tie(lhs.namespace_uri, lhs.name, lhs.value) < 102ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::tie(rhs.namespace_uri, rhs.name, rhs.value); 10375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 10475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 1056b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistatic void XMLCALL StartElementHandler(void* user_data, const char* name, const char** attrs) { 106ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 107ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 108ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski FinishPendingText(stack); 10975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 1106b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski std::unique_ptr<Element> el; 1116b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski if (stack->pending_element != nullptr) { 1126b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski el = std::move(stack->pending_element); 1136b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski } else { 1146b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski el = util::make_unique<Element>(); 1156b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski } 1166b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski 1176b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski el->line_number = XML_GetCurrentLineNumber(parser); 1186b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski el->column_number = XML_GetCurrentColumnNumber(parser); 1196b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski el->comment = std::move(stack->pending_comment); 1206b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski 121ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski SplitName(name, &el->namespace_uri, &el->name); 12275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 123ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while (*attrs) { 124ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute attribute; 125ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski SplitName(*attrs++, &attribute.namespace_uri, &attribute.name); 12648448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski attribute.value = *attrs++; 1276b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski el->attributes.push_back(std::move(attribute)); 128ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 12975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 1306b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski // Sort the attributes. 1316b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski std::sort(el->attributes.begin(), el->attributes.end(), less_attribute); 1326b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski 1336b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski // Add to the stack. 1346b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski Element* this_el = el.get(); 1356b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski if (!stack->node_stack.empty()) { 1366b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski stack->node_stack.top()->AppendChild(std::move(el)); 1376b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski } else { 1386b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski stack->root = std::move(el); 1396b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski } 1406b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski stack->node_stack.push(this_el); 14175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 14275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 143ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL EndElementHandler(void* user_data, const char* name) { 144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 145ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 146ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski FinishPendingText(stack); 14775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 148ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(!stack->node_stack.empty()); 149ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // stack->nodeStack.top()->comment = std::move(stack->pendingComment); 150ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->node_stack.pop(); 15175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 15275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 153ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinskistatic void XMLCALL CharacterDataHandler(void* user_data, const char* s, int len) { 154ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 155ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 156ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 157ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski const StringPiece str(s, len); 158ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski if (str.empty()) { 159ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return; 160ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 161ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 162ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // See if we can just append the text to a previous text node. 163ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski if (stack->last_text_node != nullptr) { 16448448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski stack->last_text_node->text.append(str.data(), str.size()); 165ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski return; 166ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 16775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 168ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski stack->last_text_node = util::make_unique<Text>(); 169ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski stack->last_text_node->line_number = XML_GetCurrentLineNumber(parser); 170ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski stack->last_text_node->column_number = XML_GetCurrentColumnNumber(parser); 17148448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski stack->last_text_node->text = str.to_string(); 17275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 17375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 174ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL CommentDataHandler(void* user_data, const char* comment) { 175ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 176ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 177ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski FinishPendingText(stack); 17875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 179ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!stack->pending_comment.empty()) { 180ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->pending_comment += '\n'; 181ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 182ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->pending_comment += comment; 18375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 18475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 185efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinskistd::unique_ptr<XmlResource> Inflate(InputStream* in, IDiagnostics* diag, const Source& source) { 186ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack stack; 187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 188efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski std::unique_ptr<std::remove_pointer<XML_Parser>::type, decltype(XML_ParserFree)*> parser = { 189efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski XML_ParserCreateNS(nullptr, kXmlNamespaceSep), XML_ParserFree}; 190efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski XML_SetUserData(parser.get(), &stack); 191efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski XML_UseParserAsHandlerArg(parser.get()); 192efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski XML_SetElementHandler(parser.get(), StartElementHandler, EndElementHandler); 193efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski XML_SetNamespaceDeclHandler(parser.get(), StartNamespaceHandler, EndNamespaceHandler); 194efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski XML_SetCharacterDataHandler(parser.get(), CharacterDataHandler); 195efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski XML_SetCommentHandler(parser.get(), CommentDataHandler); 196efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski 197efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski const char* buffer = nullptr; 198efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski size_t buffer_size = 0; 199efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski while (in->Next(reinterpret_cast<const void**>(&buffer), &buffer_size)) { 200efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski if (XML_Parse(parser.get(), buffer, buffer_size, false) == XML_STATUS_ERROR) { 201efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser.get()))) 202efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski << XML_ErrorString(XML_GetErrorCode(parser.get()))); 203efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski return {}; 2041ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 205ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 206ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 207efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski if (in->HadError()) { 208efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski diag->Error(DiagMessage(source) << in->GetError()); 209efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski return {}; 210efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski } else { 211efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski // Finish off the parsing. 212efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski if (XML_Parse(parser.get(), nullptr, 0u, true) == XML_STATUS_ERROR) { 213efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser.get()))) 214efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski << XML_ErrorString(XML_GetErrorCode(parser.get()))); 215efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski return {}; 216efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski } 217ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 218004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski return util::make_unique<XmlResource>(ResourceFile{{}, {}, ResourceFile::Type::kUnknown, source}, 219004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski StringPool{}, std::move(stack.root)); 22075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 22175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 222d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic void CopyAttributes(Element* el, android::ResXMLParser* parser, StringPool* out_pool) { 223ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const size_t attr_count = parser->getAttributeCount(); 224ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (attr_count > 0) { 225ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->attributes.reserve(attr_count); 226ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (size_t i = 0; i < attr_count; i++) { 227ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute attr; 228ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t len; 229ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char16_t* str16 = parser->getAttributeNamespace(i, &len); 230ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 231ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr.namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len)); 232ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 233ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 234ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str16 = parser->getAttributeName(i, &len); 235ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 236ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr.name = util::Utf16ToUtf8(StringPiece16(str16, len)); 237ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 238ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 2394b8ca8be4d6b0e867f5a421197fa4b5d006fd311Shane Farmer uint32_t res_id = parser->getAttributeNameResID(i); 2404b8ca8be4d6b0e867f5a421197fa4b5d006fd311Shane Farmer if (res_id > 0) { 2414b8ca8be4d6b0e867f5a421197fa4b5d006fd311Shane Farmer attr.compiled_attribute = AaptAttribute(::aapt::Attribute(), {res_id}); 2424b8ca8be4d6b0e867f5a421197fa4b5d006fd311Shane Farmer } 2434b8ca8be4d6b0e867f5a421197fa4b5d006fd311Shane Farmer 244ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str16 = parser->getAttributeStringValue(i, &len); 245ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 246ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr.value = util::Utf16ToUtf8(StringPiece16(str16, len)); 247ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 248d0f492db038c6210c1138865d816bfb134376538Adam Lesinski 249bbf429795d0558797e7ac8d1024fa5c16552e96cAdam Lesinski android::Res_value res_value; 250bbf429795d0558797e7ac8d1024fa5c16552e96cAdam Lesinski if (parser->getAttributeValue(i, &res_value) > 0) { 251e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski // Only compile the value if it is not a string, or it is a string that differs from 252e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski // the raw attribute value. 253e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski int32_t raw_value_idx = parser->getAttributeValueStringID(i); 254e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski if (res_value.dataType != android::Res_value::TYPE_STRING || raw_value_idx < 0 || 255e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski static_cast<uint32_t>(raw_value_idx) != res_value.data) { 256e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski attr.compiled_value = ResourceUtils::ParseBinaryResValue( 257e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski ResourceType::kAnim, {}, parser->getStrings(), res_value, out_pool); 258e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski } 259bbf429795d0558797e7ac8d1024fa5c16552e96cAdam Lesinski } 260d0f492db038c6210c1138865d816bfb134376538Adam Lesinski 261ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->attributes.push_back(std::move(attr)); 26275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 263ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 26475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 26575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 2668780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinskistd::unique_ptr<XmlResource> Inflate(const void* data, size_t len, std::string* out_error) { 267ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // We import the android namespace because on Windows NO_ERROR is a macro, not 2686b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski // an enum, which causes errors when qualifying it with android:: 269ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski using namespace android; 270803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski 271e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski std::unique_ptr<XmlResource> xml_resource = util::make_unique<XmlResource>(); 272e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski 2736b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski std::stack<Element*> node_stack; 2746b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski std::unique_ptr<Element> pending_element; 27575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 276ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResXMLTree tree; 2778780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski if (tree.setTo(data, len) != NO_ERROR) { 2788780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski if (out_error != nullptr) { 2798780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski *out_error = "failed to initialize ResXMLTree"; 2808780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski } 281ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 282ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 283ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 284ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResXMLParser::event_code_t code; 2856b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT && code != ResXMLParser::END_DOCUMENT) { 286ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Node> new_node; 287ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski switch (code) { 288ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::START_NAMESPACE: { 2896b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski NamespaceDecl decl; 2901ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski decl.line_number = tree.getLineNumber(); 2911ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski 292ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t len; 293ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char16_t* str16 = tree.getNamespacePrefix(&len); 294ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 2956b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski decl.prefix = util::Utf16ToUtf8(StringPiece16(str16, len)); 296ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 297ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 298ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str16 = tree.getNamespaceUri(&len); 299ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 3006b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski decl.uri = util::Utf16ToUtf8(StringPiece16(str16, len)); 3016b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski } 3026b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski 3036b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski if (pending_element == nullptr) { 3046b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski pending_element = util::make_unique<Element>(); 305ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 3061ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski pending_element->namespace_decls.push_back(std::move(decl)); 307ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 308ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 309ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 310ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::START_TAG: { 3116b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski std::unique_ptr<Element> el; 3126b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski if (pending_element != nullptr) { 3136b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski el = std::move(pending_element); 3146b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski } else { 3156b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski el = util::make_unique<Element>(); 3166b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski } 3171ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski el->line_number = tree.getLineNumber(); 3186b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski 319ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t len; 320ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char16_t* str16 = tree.getElementNamespace(&len); 321ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 3226b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski el->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len)); 323ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 32475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 325ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str16 = tree.getElementName(&len); 326ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 3276b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski el->name = util::Utf16ToUtf8(StringPiece16(str16, len)); 32875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 32975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 3306b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski Element* this_el = el.get(); 331e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski CopyAttributes(el.get(), &tree, &xml_resource->string_pool); 332ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 3336b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski if (!node_stack.empty()) { 3346b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski node_stack.top()->AppendChild(std::move(el)); 3356b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski } else { 336e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski xml_resource->root = std::move(el); 3376b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski } 3386b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski node_stack.push(this_el); 339ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 340ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 341ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 342ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::TEXT: { 3436b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski std::unique_ptr<Text> text = util::make_unique<Text>(); 3446b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski text->line_number = tree.getLineNumber(); 345ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t len; 346ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char16_t* str16 = tree.getText(&len); 347ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 3486b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski text->text = util::Utf16ToUtf8(StringPiece16(str16, len)); 34975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 3506b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski CHECK(!node_stack.empty()); 3516b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski node_stack.top()->AppendChild(std::move(text)); 352ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 353ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 354ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 355ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::END_NAMESPACE: 3566b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski break; 3576b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski 358ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::END_TAG: 359ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(!node_stack.empty()); 360ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node_stack.pop(); 361ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 362ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 363ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski default: 364ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski LOG(FATAL) << "unhandled XML chunk type"; 365ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 36675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 367ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 368e1094a2e232277a719025aa5c97c492502c34f5bAdam Lesinski return xml_resource; 3695eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski} 3705eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 3718780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinskistd::unique_ptr<XmlResource> XmlResource::Clone() const { 3728780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski std::unique_ptr<XmlResource> cloned = util::make_unique<XmlResource>(file); 3738780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski if (root != nullptr) { 3748780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski cloned->root = root->CloneElement([&](const xml::Element& src, xml::Element* dst) { 3758780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski dst->attributes.reserve(src.attributes.size()); 3768780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski for (const xml::Attribute& attr : src.attributes) { 3778780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski xml::Attribute cloned_attr; 3788780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski cloned_attr.name = attr.name; 3798780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski cloned_attr.namespace_uri = attr.namespace_uri; 3808780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski cloned_attr.value = attr.value; 3818780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski cloned_attr.compiled_attribute = attr.compiled_attribute; 3828780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski if (attr.compiled_value != nullptr) { 3838780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski cloned_attr.compiled_value.reset(attr.compiled_value->Clone(&cloned->string_pool)); 3848780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski } 3858780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski dst->attributes.push_back(std::move(cloned_attr)); 3868780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski } 3878780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski }); 3888780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski } 3898780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski return cloned; 3908780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski} 3918780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski 392ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* FindRootElement(Node* node) { 3936b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski if (node == nullptr) { 394ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return nullptr; 395ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 396ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 3976b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski while (node->parent != nullptr) { 3986b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski node = node->parent; 399ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 4006b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski return NodeCast<Element>(node); 401ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 402ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 4036b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Element::AppendChild(std::unique_ptr<Node> child) { 404ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski child->parent = this; 405ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski children.push_back(std::move(child)); 40675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 40775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 4086b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Element::InsertChild(size_t index, std::unique_ptr<Node> child) { 409e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski child->parent = this; 410e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski children.insert(children.begin() + index, std::move(child)); 411e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski} 412e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski 4136b372991296c9f2bd6f8f8847dcd23d50970d06dAdam LesinskiAttribute* Element::FindAttribute(const StringPiece& ns, const StringPiece& name) { 4148780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski return const_cast<Attribute*>(static_cast<const Element*>(this)->FindAttribute(ns, name)); 41575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 41675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 417c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskiconst Attribute* Element::FindAttribute(const StringPiece& ns, const StringPiece& name) const { 418c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski for (const auto& attr : attributes) { 419c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski if (ns == attr.namespace_uri && name == attr.name) { 420c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski return &attr; 421c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski } 422c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski } 423c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski return nullptr; 424c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski} 425c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 426c6284379a5dde6bc5927409eff292db2f0add578Adam LesinskiAttribute* Element::FindOrCreateAttribute(const StringPiece& ns, const StringPiece& name) { 427c6284379a5dde6bc5927409eff292db2f0add578Adam Lesinski Attribute* attr = FindAttribute(ns, name); 428c6284379a5dde6bc5927409eff292db2f0add578Adam Lesinski if (attr == nullptr) { 429c6284379a5dde6bc5927409eff292db2f0add578Adam Lesinski attributes.push_back(Attribute{ns.to_string(), name.to_string()}); 430c6284379a5dde6bc5927409eff292db2f0add578Adam Lesinski attr = &attributes.back(); 431c6284379a5dde6bc5927409eff292db2f0add578Adam Lesinski } 432c6284379a5dde6bc5927409eff292db2f0add578Adam Lesinski return attr; 433c6284379a5dde6bc5927409eff292db2f0add578Adam Lesinski} 434c6284379a5dde6bc5927409eff292db2f0add578Adam Lesinski 435ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* Element::FindChild(const StringPiece& ns, const StringPiece& name) { 436ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return FindChildWithAttribute(ns, name, {}, {}, {}); 43775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 43875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 4398780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinskiconst Element* Element::FindChild(const StringPiece& ns, const StringPiece& name) const { 4408780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski return FindChildWithAttribute(ns, name, {}, {}, {}); 4418780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski} 4428780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski 4436b372991296c9f2bd6f8f8847dcd23d50970d06dAdam LesinskiElement* Element::FindChildWithAttribute(const StringPiece& ns, const StringPiece& name, 4446b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski const StringPiece& attr_ns, const StringPiece& attr_name, 445ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& attr_value) { 4468780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski return const_cast<Element*>(static_cast<const Element*>(this)->FindChildWithAttribute( 4478780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski ns, name, attr_ns, attr_name, attr_value)); 4488780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski} 4498780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski 4508780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinskiconst Element* Element::FindChildWithAttribute(const StringPiece& ns, const StringPiece& name, 4518780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski const StringPiece& attr_ns, 4528780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski const StringPiece& attr_name, 4538780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski const StringPiece& attr_value) const { 4548780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski for (const auto& child : children) { 4558780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski if (const Element* el = NodeCast<Element>(child.get())) { 456ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (ns == el->namespace_uri && name == el->name) { 457ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (attr_ns.empty() && attr_name.empty()) { 458ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return el; 45975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 46075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 4618780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski const Attribute* attr = el->FindAttribute(attr_ns, attr_name); 462ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (attr && attr_value == attr->value) { 463ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return el; 46475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 465ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 46675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 467ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 468ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return nullptr; 46975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 47075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 471ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::vector<Element*> Element::GetChildElements() { 472ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<Element*> elements; 473ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto& child_node : children) { 4746b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski if (Element* child = NodeCast<Element>(child_node.get())) { 4756b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski elements.push_back(child); 4765eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski } 477ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 478ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return elements; 4795eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski} 4805eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 4816b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistd::unique_ptr<Node> Element::Clone(const ElementCloneFunc& el_cloner) const { 482ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto el = util::make_unique<Element>(); 4836b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski el->namespace_decls = namespace_decls; 484ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->comment = comment; 485ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->line_number = line_number; 486ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->column_number = column_number; 487ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->name = name; 488ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->namespace_uri = namespace_uri; 489ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->attributes.reserve(attributes.size()); 490c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski el_cloner(*this, el.get()); 491ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->children.reserve(children.size()); 492ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::unique_ptr<xml::Node>& child : children) { 493c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski el->AppendChild(child->Clone(el_cloner)); 494ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 495ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return std::move(el); 4965eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski} 4975eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 4986b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistd::unique_ptr<Element> Element::CloneElement(const ElementCloneFunc& el_cloner) const { 4996b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski return std::unique_ptr<Element>(static_cast<Element*>(Clone(el_cloner).release())); 5006b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski} 5016b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski 5026b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Element::Accept(Visitor* visitor) { 5036b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski visitor->BeforeVisitElement(this); 5046b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski visitor->Visit(this); 5056b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski visitor->AfterVisitElement(this); 5066b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski} 5076b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski 508d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinskivoid Element::Accept(ConstVisitor* visitor) const { 509d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski visitor->BeforeVisitElement(this); 510d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski visitor->Visit(this); 511d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski visitor->AfterVisitElement(this); 512d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski} 513d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski 5146b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskistd::unique_ptr<Node> Text::Clone(const ElementCloneFunc&) const { 515ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto t = util::make_unique<Text>(); 516ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski t->comment = comment; 517ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski t->line_number = line_number; 518ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski t->column_number = column_number; 519ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski t->text = text; 520ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return std::move(t); 521ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski} 522467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 5236b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid Text::Accept(Visitor* visitor) { 5246b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski visitor->Visit(this); 5256b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski} 526ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 527d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinskivoid Text::Accept(ConstVisitor* visitor) const { 528d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski visitor->Visit(this); 529d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski} 530d3ffa844f5a07756009f019e13806e253d1bb119Adam Lesinski 5316b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid PackageAwareVisitor::BeforeVisitElement(Element* el) { 5326b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski std::vector<PackageDecl> decls; 5336b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski for (const NamespaceDecl& decl : el->namespace_decls) { 5346b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski if (Maybe<ExtractedPackage> maybe_package = ExtractPackageFromNamespace(decl.uri)) { 5356b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski decls.push_back(PackageDecl{decl.prefix, std::move(maybe_package.value())}); 5366b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski } 537ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 5386b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski package_decls_.push_back(std::move(decls)); 5396b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski} 5406b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski 5416b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinskivoid PackageAwareVisitor::AfterVisitElement(Element* el) { 5426b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski package_decls_.pop_back(); 543467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 544467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 5451ef0fa9d7242b1926543bc49e35905d1be02a781Adam LesinskiMaybe<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias(const StringPiece& alias) const { 546ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (alias.empty()) { 5471ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski return ExtractedPackage{{}, false /*private*/}; 548ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 549ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 550ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const auto rend = package_decls_.rend(); 551ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) { 5526b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski const std::vector<PackageDecl>& decls = *iter; 5536b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski const auto rend2 = decls.rend(); 5546b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski for (auto iter2 = decls.rbegin(); iter2 != rend2; ++iter2) { 5556b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski const PackageDecl& decl = *iter2; 5566b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski if (alias == decl.prefix) { 5576b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski if (decl.package.package.empty()) { 5581ef0fa9d7242b1926543bc49e35905d1be02a781Adam Lesinski return ExtractedPackage{{}, decl.package.private_namespace}; 5596b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski } 5606b372991296c9f2bd6f8f8847dcd23d50970d06dAdam Lesinski return decl.package; 561ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 562ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 563ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 564ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 565467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 566467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 567ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski} // namespace xml 568ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski} // namespace aapt 569