XmlDom.cpp revision efeb7af13be4446ce4a511a2ca707691e9a67c1e
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 { 42ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<xml::Node> root; 43ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::stack<xml::Node*> node_stack; 44ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string pending_comment; 45ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski std::unique_ptr<xml::Text> last_text_node; 4675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}; 4775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 4875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/** 4975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Extracts the namespace and name of an expanded element or attribute name. 5075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */ 51ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void SplitName(const char* name, std::string* out_ns, 52ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string* out_name) { 53ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char* p = name; 54ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while (*p != 0 && *p != kXmlNamespaceSep) { 55ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski p++; 56ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 57ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 58ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (*p == 0) { 59ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski out_ns->clear(); 60d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski out_name->assign(name); 61ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else { 62d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski out_ns->assign(name, (p - name)); 63d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski out_name->assign(p + 1); 64ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 6575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 6675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 67ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinskistatic void FinishPendingText(Stack* stack) { 68ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski if (stack->last_text_node != nullptr) { 6948448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski if (!stack->last_text_node->text.empty()) { 70ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski stack->node_stack.top()->AppendChild(std::move(stack->last_text_node)); 71ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski } else { 72ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski // Drop an empty text node. 73ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski } 7448448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski stack->last_text_node = nullptr; 75ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski } 76ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski} 77ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski 78ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void AddToStack(Stack* stack, XML_Parser parser, 79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Node> node) { 80ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->line_number = XML_GetCurrentLineNumber(parser); 81ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->column_number = XML_GetCurrentColumnNumber(parser); 82ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 83ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Node* this_node = node.get(); 84ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!stack->node_stack.empty()) { 85e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski stack->node_stack.top()->AppendChild(std::move(node)); 86ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else { 87ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->root = std::move(node); 88ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 89ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!NodeCast<Text>(this_node)) { 91ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->node_stack.push(this_node); 92ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 9375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 9475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 95ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix, 96ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char* uri) { 97ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 98ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 99ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski FinishPendingText(stack); 10075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 101ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Namespace> ns = util::make_unique<Namespace>(); 102ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (prefix) { 103d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski ns->namespace_prefix = prefix; 104ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 10575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 106ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (uri) { 107d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski ns->namespace_uri = uri; 108ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 10975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 110ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski AddToStack(stack, parser, std::move(ns)); 11175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 11275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 113ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL EndNamespaceHandler(void* user_data, const char* prefix) { 114ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 115ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 116ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski FinishPendingText(stack); 11775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 118ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(!stack->node_stack.empty()); 119ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->node_stack.pop(); 12075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 12175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 122ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic bool less_attribute(const Attribute& lhs, const Attribute& rhs) { 123ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return std::tie(lhs.namespace_uri, lhs.name, lhs.value) < 124ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::tie(rhs.namespace_uri, rhs.name, rhs.value); 12575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 12675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 127ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL StartElementHandler(void* user_data, const char* name, 128ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char** attrs) { 129ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 130ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 131ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski FinishPendingText(stack); 13275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 133ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Element> el = util::make_unique<Element>(); 134ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski SplitName(name, &el->namespace_uri, &el->name); 13575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 136ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while (*attrs) { 137ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute attribute; 138ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski SplitName(*attrs++, &attribute.namespace_uri, &attribute.name); 13948448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski attribute.value = *attrs++; 14075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 141ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // Insert in sorted order. 14248448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski auto iter = std::lower_bound(el->attributes.begin(), el->attributes.end(), attribute, 14348448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski less_attribute); 144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->attributes.insert(iter, std::move(attribute)); 145ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 14675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 147ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->comment = std::move(stack->pending_comment); 148ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski AddToStack(stack, parser, std::move(el)); 14975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 15075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 151ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL EndElementHandler(void* user_data, const char* name) { 152ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 153ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 154ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski FinishPendingText(stack); 15575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 156ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(!stack->node_stack.empty()); 157ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // stack->nodeStack.top()->comment = std::move(stack->pendingComment); 158ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->node_stack.pop(); 15975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 16075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 161ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinskistatic void XMLCALL CharacterDataHandler(void* user_data, const char* s, int len) { 162ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 163ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 164ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 165ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski const StringPiece str(s, len); 166ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski if (str.empty()) { 167ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return; 168ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 169ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 170ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // See if we can just append the text to a previous text node. 171ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski if (stack->last_text_node != nullptr) { 17248448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski stack->last_text_node->text.append(str.data(), str.size()); 173ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski return; 174ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 17575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 176ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski stack->last_text_node = util::make_unique<Text>(); 177ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski stack->last_text_node->line_number = XML_GetCurrentLineNumber(parser); 178ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski stack->last_text_node->column_number = XML_GetCurrentColumnNumber(parser); 17948448e8a310e72eb2846ad0f86672ce4f0b47e47Adam Lesinski stack->last_text_node->text = str.to_string(); 18075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 18175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 182ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL CommentDataHandler(void* user_data, const char* comment) { 183ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 184ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 185ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski FinishPendingText(stack); 18675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!stack->pending_comment.empty()) { 188ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->pending_comment += '\n'; 189ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 190ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->pending_comment += comment; 19175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 19275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 193efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinskistd::unique_ptr<XmlResource> Inflate(InputStream* in, IDiagnostics* diag, const Source& source) { 194ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack stack; 195ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 196efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski std::unique_ptr<std::remove_pointer<XML_Parser>::type, decltype(XML_ParserFree)*> parser = { 197efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski XML_ParserCreateNS(nullptr, kXmlNamespaceSep), XML_ParserFree}; 198efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski XML_SetUserData(parser.get(), &stack); 199efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski XML_UseParserAsHandlerArg(parser.get()); 200efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski XML_SetElementHandler(parser.get(), StartElementHandler, EndElementHandler); 201efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski XML_SetNamespaceDeclHandler(parser.get(), StartNamespaceHandler, EndNamespaceHandler); 202efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski XML_SetCharacterDataHandler(parser.get(), CharacterDataHandler); 203efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski XML_SetCommentHandler(parser.get(), CommentDataHandler); 204efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski 205efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski const char* buffer = nullptr; 206efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski size_t buffer_size = 0; 207efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski while (in->Next(reinterpret_cast<const void**>(&buffer), &buffer_size)) { 208efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski if (XML_Parse(parser.get(), buffer, buffer_size, false) == XML_STATUS_ERROR) { 209efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser.get()))) 210efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski << XML_ErrorString(XML_GetErrorCode(parser.get()))); 211efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski return {}; 2121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 213ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 214ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 215efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski if (in->HadError()) { 216efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski diag->Error(DiagMessage(source) << in->GetError()); 217efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski return {}; 218efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski } else { 219efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski // Finish off the parsing. 220efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski if (XML_Parse(parser.get(), nullptr, 0u, true) == XML_STATUS_ERROR) { 221efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser.get()))) 222efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski << XML_ErrorString(XML_GetErrorCode(parser.get()))); 223efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski return {}; 224efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski } 225ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 226efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski return util::make_unique<XmlResource>(ResourceFile{{}, {}, source}, StringPool{}, 227efeb7af13be4446ce4a511a2ca707691e9a67c1eAdam Lesinski std::move(stack.root)); 22875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 22975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 230d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistatic void CopyAttributes(Element* el, android::ResXMLParser* parser, StringPool* out_pool) { 231ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const size_t attr_count = parser->getAttributeCount(); 232ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (attr_count > 0) { 233ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->attributes.reserve(attr_count); 234ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (size_t i = 0; i < attr_count; i++) { 235ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute attr; 236ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t len; 237ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char16_t* str16 = parser->getAttributeNamespace(i, &len); 238ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 239ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr.namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len)); 240ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 241ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 242ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str16 = parser->getAttributeName(i, &len); 243ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 244ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr.name = util::Utf16ToUtf8(StringPiece16(str16, len)); 245ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 246ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 247ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str16 = parser->getAttributeStringValue(i, &len); 248ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 249ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr.value = util::Utf16ToUtf8(StringPiece16(str16, len)); 250ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 251d0f492db038c6210c1138865d816bfb134376538Adam Lesinski 252d0f492db038c6210c1138865d816bfb134376538Adam Lesinski android::Res_value res_value; 253d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (parser->getAttributeValue(i, &res_value) > 0) { 254d0f492db038c6210c1138865d816bfb134376538Adam Lesinski attr.compiled_value = ResourceUtils::ParseBinaryResValue( 255d0f492db038c6210c1138865d816bfb134376538Adam Lesinski ResourceType::kAnim, {}, parser->getStrings(), res_value, out_pool); 256d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 257d0f492db038c6210c1138865d816bfb134376538Adam Lesinski 258ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->attributes.push_back(std::move(attr)); 25975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 260ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 26175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 26275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 263d0f492db038c6210c1138865d816bfb134376538Adam Lesinskistd::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len, IDiagnostics* diag, 264d0f492db038c6210c1138865d816bfb134376538Adam Lesinski const Source& source) { 265ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // We import the android namespace because on Windows NO_ERROR is a macro, not 266ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // an enum, which 267ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // causes errors when qualifying it with android:: 268ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski using namespace android; 269803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski 270d0f492db038c6210c1138865d816bfb134376538Adam Lesinski StringPool string_pool; 271ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Node> root; 272ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::stack<Node*> node_stack; 27375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 274ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResXMLTree tree; 275ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (tree.setTo(data, data_len) != NO_ERROR) { 276ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 277ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 278ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 279ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResXMLParser::event_code_t code; 280ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT && 281ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski code != ResXMLParser::END_DOCUMENT) { 282ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Node> new_node; 283ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski switch (code) { 284ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::START_NAMESPACE: { 285ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Namespace> node = util::make_unique<Namespace>(); 286ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t len; 287ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char16_t* str16 = tree.getNamespacePrefix(&len); 288ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 289ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->namespace_prefix = util::Utf16ToUtf8(StringPiece16(str16, len)); 290ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 291ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 292ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str16 = tree.getNamespaceUri(&len); 293ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 294ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len)); 295ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 296ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski new_node = std::move(node); 297ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 298ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 299ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 300ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::START_TAG: { 301ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Element> node = util::make_unique<Element>(); 302ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t len; 303ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char16_t* str16 = tree.getElementNamespace(&len); 304ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 305ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len)); 306ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 30775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 308ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str16 = tree.getElementName(&len); 309ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 310ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->name = util::Utf16ToUtf8(StringPiece16(str16, len)); 31175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 31275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 313d0f492db038c6210c1138865d816bfb134376538Adam Lesinski CopyAttributes(node.get(), &tree, &string_pool); 314ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 315ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski new_node = std::move(node); 316ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 317ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 318ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 319ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::TEXT: { 320ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Text> node = util::make_unique<Text>(); 321ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t len; 322ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char16_t* str16 = tree.getText(&len); 323ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 324ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->text = util::Utf16ToUtf8(StringPiece16(str16, len)); 32575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 326ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski new_node = std::move(node); 327ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 328ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 329ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 330ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::END_NAMESPACE: 331ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::END_TAG: 332ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(!node_stack.empty()); 333ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node_stack.pop(); 334ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 335ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 336ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski default: 337ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski LOG(FATAL) << "unhandled XML chunk type"; 338ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 33975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 34075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 341ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (new_node) { 342ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski new_node->line_number = tree.getLineNumber(); 343ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 344ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Node* this_node = new_node.get(); 345ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!root) { 346ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(node_stack.empty()) << "node stack should be empty"; 347ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski root = std::move(new_node); 348ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else { 349ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(!node_stack.empty()) << "node stack should not be empty"; 350e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski node_stack.top()->AppendChild(std::move(new_node)); 351ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 352ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 353ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!NodeCast<Text>(this_node)) { 354ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node_stack.push(this_node); 355ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 3565eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski } 357ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 358ea134e08d70d156bdd17714d5f9ab9c44c91d4faAdam Lesinski return util::make_unique<XmlResource>(ResourceFile{}, std::move(string_pool), std::move(root)); 3595eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski} 3605eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 361c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskistd::unique_ptr<Node> Namespace::Clone(const ElementCloneFunc& el_cloner) { 362ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto ns = util::make_unique<Namespace>(); 363ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->comment = comment; 364ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->line_number = line_number; 365ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->column_number = column_number; 366ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->namespace_prefix = namespace_prefix; 367ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->namespace_uri = namespace_uri; 368ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->children.reserve(children.size()); 369ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::unique_ptr<xml::Node>& child : children) { 370c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski ns->AppendChild(child->Clone(el_cloner)); 371ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 372ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return std::move(ns); 373467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 374467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 375ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* FindRootElement(XmlResource* doc) { 376ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return FindRootElement(doc->root.get()); 377ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski} 378ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 379ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* FindRootElement(Node* node) { 380ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!node) { 381ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return nullptr; 382ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 383ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 384ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Element* el = nullptr; 385ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while ((el = NodeCast<Element>(node)) == nullptr) { 386ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (node->children.empty()) { 387ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return nullptr; 388ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 389ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // We are looking for the first element, and namespaces can only have one 390ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // child. 391ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node = node->children.front().get(); 392ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 393ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return el; 394ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 395ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 396e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinskivoid Node::AppendChild(std::unique_ptr<Node> child) { 397ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski child->parent = this; 398ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski children.push_back(std::move(child)); 39975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 40075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 401e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinskivoid Node::InsertChild(size_t index, std::unique_ptr<Node> child) { 402e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski child->parent = this; 403e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski children.insert(children.begin() + index, std::move(child)); 404e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski} 405e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski 406ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiAttribute* Element::FindAttribute(const StringPiece& ns, 407ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& name) { 408ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto& attr : attributes) { 409ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (ns == attr.namespace_uri && name == attr.name) { 410ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return &attr; 41175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 412ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 413ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return nullptr; 41475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 41575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 416c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskiconst Attribute* Element::FindAttribute(const StringPiece& ns, const StringPiece& name) const { 417c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski for (const auto& attr : attributes) { 418c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski if (ns == attr.namespace_uri && name == attr.name) { 419c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski return &attr; 420c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski } 421c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski } 422c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski return nullptr; 423c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski} 424c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski 425ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* Element::FindChild(const StringPiece& ns, const StringPiece& name) { 426ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return FindChildWithAttribute(ns, name, {}, {}, {}); 42775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 42875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 429ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* Element::FindChildWithAttribute(const StringPiece& ns, 430ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& name, 431ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& attr_ns, 432ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& attr_name, 433ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& attr_value) { 434ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto& child_node : children) { 435ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Node* child = child_node.get(); 436ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while (NodeCast<Namespace>(child)) { 437ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (child->children.empty()) { 438ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 439ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 440ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski child = child->children[0].get(); 44175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 44275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 443ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (Element* el = NodeCast<Element>(child)) { 444ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (ns == el->namespace_uri && name == el->name) { 445ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (attr_ns.empty() && attr_name.empty()) { 446ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return el; 44775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 44875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 449ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = el->FindAttribute(attr_ns, attr_name); 450ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (attr && attr_value == attr->value) { 451ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return el; 45275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 453ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 45475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 455ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 456ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return nullptr; 45775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 45875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 459ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::vector<Element*> Element::GetChildElements() { 460ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<Element*> elements; 461ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto& child_node : children) { 462ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Node* child = child_node.get(); 463ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while (NodeCast<Namespace>(child)) { 464ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (child->children.empty()) { 465ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 466ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 467ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski child = child->children[0].get(); 4685eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski } 4695eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 470ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (Element* el = NodeCast<Element>(child)) { 471ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski elements.push_back(el); 4725eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski } 473ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 474ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return elements; 4755eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski} 4765eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 477c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskistd::unique_ptr<Node> Element::Clone(const ElementCloneFunc& el_cloner) { 478ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto el = util::make_unique<Element>(); 479ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->comment = comment; 480ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->line_number = line_number; 481ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->column_number = column_number; 482ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->name = name; 483ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->namespace_uri = namespace_uri; 484ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->attributes.reserve(attributes.size()); 485c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski el_cloner(*this, el.get()); 486ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->children.reserve(children.size()); 487ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::unique_ptr<xml::Node>& child : children) { 488c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinski el->AppendChild(child->Clone(el_cloner)); 489ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 490ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return std::move(el); 4915eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski} 4925eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 493c744ae8aca97edfb2422598ea620e8219449fa9bAdam Lesinskistd::unique_ptr<Node> Text::Clone(const ElementCloneFunc&) { 494ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto t = util::make_unique<Text>(); 495ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski t->comment = comment; 496ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski t->line_number = line_number; 497ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski t->column_number = column_number; 498ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski t->text = text; 499ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return std::move(t); 500ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski} 501467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 502ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskivoid PackageAwareVisitor::Visit(Namespace* ns) { 503ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool added = false; 504ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (Maybe<ExtractedPackage> maybe_package = 505ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ExtractPackageFromNamespace(ns->namespace_uri)) { 506ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ExtractedPackage& package = maybe_package.value(); 507ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski package_decls_.push_back( 508ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski PackageDecl{ns->namespace_prefix, std::move(package)}); 509ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski added = true; 510ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 511ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 512ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Visitor::Visit(ns); 513ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 514ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (added) { 515ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski package_decls_.pop_back(); 516ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 517467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 518467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 519ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiMaybe<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias( 520ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& alias, const StringPiece& local_package) const { 521ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (alias.empty()) { 522d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski return ExtractedPackage{local_package.to_string(), false /* private */}; 523ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 524ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 525ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const auto rend = package_decls_.rend(); 526ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) { 527ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (alias == iter->prefix) { 528ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (iter->package.package.empty()) { 529d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski return ExtractedPackage{local_package.to_string(), iter->package.private_namespace}; 530ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 531ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return iter->package; 532ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 533ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 534ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 535467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 536467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 537ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski} // namespace xml 538ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski} // namespace aapt 539