XmlDom.cpp revision ac6edc501b61e14e3b70ccbbd4d8ed112d92b96c
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 28ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "XmlPullParser.h" 29ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "util/Util.h" 30ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 31d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinskiusing android::StringPiece; 32d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinskiusing android::StringPiece16; 33d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski 3475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace aapt { 3575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace xml { 3675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 3775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskiconstexpr char kXmlNamespaceSep = 1; 3875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 3975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistruct Stack { 40ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<xml::Node> root; 41ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::stack<xml::Node*> node_stack; 42ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string pending_comment; 43ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski std::unique_ptr<xml::Text> last_text_node; 44ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski util::StringBuilder pending_text; 4575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}; 4675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 4775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/** 4875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Extracts the namespace and name of an expanded element or attribute name. 4975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */ 50ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void SplitName(const char* name, std::string* out_ns, 51ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string* out_name) { 52ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char* p = name; 53ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while (*p != 0 && *p != kXmlNamespaceSep) { 54ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski p++; 55ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 56ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 57ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (*p == 0) { 58ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski out_ns->clear(); 59d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski out_name->assign(name); 60ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else { 61d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski out_ns->assign(name, (p - name)); 62d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski out_name->assign(p + 1); 63ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 6475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 6575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 66ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinskistatic void FinishPendingText(Stack* stack) { 67ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski if (stack->last_text_node != nullptr) { 68ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski if (!stack->pending_text.IsEmpty()) { 69ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski stack->last_text_node->text = stack->pending_text.ToString(); 70ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski stack->pending_text = {}; 71ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski stack->node_stack.top()->AppendChild(std::move(stack->last_text_node)); 72ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski } else { 73ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski // Drop an empty text node. 74ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski stack->last_text_node = nullptr; 75ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski } 76ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski } 77ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski} 78ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski 79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void AddToStack(Stack* stack, XML_Parser parser, 80ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Node> node) { 81ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->line_number = XML_GetCurrentLineNumber(parser); 82ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->column_number = XML_GetCurrentColumnNumber(parser); 83ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 84ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Node* this_node = node.get(); 85ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!stack->node_stack.empty()) { 86e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski stack->node_stack.top()->AppendChild(std::move(node)); 87ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else { 88ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->root = std::move(node); 89ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 91ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!NodeCast<Text>(this_node)) { 92ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->node_stack.push(this_node); 93ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 9475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 9575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 96ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix, 97ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char* uri) { 98ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 99ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 100ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski FinishPendingText(stack); 10175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 102ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Namespace> ns = util::make_unique<Namespace>(); 103ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (prefix) { 104d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski ns->namespace_prefix = prefix; 105ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 10675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 107ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (uri) { 108d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski ns->namespace_uri = uri; 109ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 11075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 111ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski AddToStack(stack, parser, std::move(ns)); 11275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 11375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 114ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL EndNamespaceHandler(void* user_data, const char* prefix) { 115ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 116ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 117ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski FinishPendingText(stack); 11875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 119ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(!stack->node_stack.empty()); 120ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->node_stack.pop(); 12175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 12275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 123ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic bool less_attribute(const Attribute& lhs, const Attribute& rhs) { 124ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return std::tie(lhs.namespace_uri, lhs.name, lhs.value) < 125ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::tie(rhs.namespace_uri, rhs.name, rhs.value); 12675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 12775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 128ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL StartElementHandler(void* user_data, const char* name, 129ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char** attrs) { 130ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 131ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 132ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski FinishPendingText(stack); 13375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 134ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Element> el = util::make_unique<Element>(); 135ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski SplitName(name, &el->namespace_uri, &el->name); 13675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 137ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while (*attrs) { 138ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute attribute; 139ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski SplitName(*attrs++, &attribute.namespace_uri, &attribute.name); 140ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski util::StringBuilder builder; 141ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski builder.Append(*attrs++); 142ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski attribute.value = builder.ToString(); 14375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // Insert in sorted order. 145ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto iter = std::lower_bound(el->attributes.begin(), el->attributes.end(), 146ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attribute, less_attribute); 147ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->attributes.insert(iter, std::move(attribute)); 148ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 14975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 150ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->comment = std::move(stack->pending_comment); 151ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski AddToStack(stack, parser, std::move(el)); 15275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 15375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 154ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL EndElementHandler(void* user_data, const char* name) { 155ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 156ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 157ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski FinishPendingText(stack); 15875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 159ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(!stack->node_stack.empty()); 160ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // stack->nodeStack.top()->comment = std::move(stack->pendingComment); 161ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->node_stack.pop(); 16275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 16375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 164ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinskistatic void XMLCALL CharacterDataHandler(void* user_data, const char* s, int len) { 165ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 166ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 167ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 168ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski const StringPiece str(s, len); 169ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski if (str.empty()) { 170ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return; 171ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 172ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 173ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // See if we can just append the text to a previous text node. 174ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski if (stack->last_text_node != nullptr) { 175ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski stack->pending_text.Append(str); 176ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski return; 177ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 17875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 179ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski stack->last_text_node = util::make_unique<Text>(); 180ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski stack->last_text_node->line_number = XML_GetCurrentLineNumber(parser); 181ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski stack->last_text_node->column_number = XML_GetCurrentColumnNumber(parser); 182ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski stack->pending_text.Append(str); 18375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 18475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 185ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL CommentDataHandler(void* user_data, const char* comment) { 186ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 188ac6edc501b61e14e3b70ccbbd4d8ed112d92b96cAdam Lesinski FinishPendingText(stack); 18975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 190ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!stack->pending_comment.empty()) { 191ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->pending_comment += '\n'; 192ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 193ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->pending_comment += comment; 19475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 19575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 196ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<XmlResource> Inflate(std::istream* in, IDiagnostics* diag, 197ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const Source& source) { 198ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack stack; 199ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 200ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = XML_ParserCreateNS(nullptr, kXmlNamespaceSep); 201ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_SetUserData(parser, &stack); 202ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_UseParserAsHandlerArg(parser); 203ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_SetElementHandler(parser, StartElementHandler, EndElementHandler); 204ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_SetNamespaceDeclHandler(parser, StartNamespaceHandler, 205ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EndNamespaceHandler); 206ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_SetCharacterDataHandler(parser, CharacterDataHandler); 207ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_SetCommentHandler(parser, CommentDataHandler); 208ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 209ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski char buffer[1024]; 210ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while (!in->eof()) { 211ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski in->read(buffer, sizeof(buffer) / sizeof(buffer[0])); 212ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (in->bad() && !in->eof()) { 213ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack.root = {}; 214ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(source) << strerror(errno)); 215ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 21675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 21775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 218ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (XML_Parse(parser, buffer, in->gcount(), in->eof()) == 219ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_STATUS_ERROR) { 220ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack.root = {}; 221ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser))) 222ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski << XML_ErrorString(XML_GetErrorCode(parser))); 223ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 2241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 225ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 226ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 227ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_ParserFree(parser); 228ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (stack.root) { 229ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return util::make_unique<XmlResource>(ResourceFile{{}, {}, source}, 230ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::move(stack.root)); 231ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 232ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 23375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 23475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 235ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void CopyAttributes(Element* el, android::ResXMLParser* parser) { 236ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const size_t attr_count = parser->getAttributeCount(); 237ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (attr_count > 0) { 238ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->attributes.reserve(attr_count); 239ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (size_t i = 0; i < attr_count; i++) { 240ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute attr; 241ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t len; 242ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char16_t* str16 = parser->getAttributeNamespace(i, &len); 243ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 244ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr.namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len)); 245ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 246ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 247ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str16 = parser->getAttributeName(i, &len); 248ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 249ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr.name = util::Utf16ToUtf8(StringPiece16(str16, len)); 250ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 251ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 252ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str16 = parser->getAttributeStringValue(i, &len); 253ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 254ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr.value = util::Utf16ToUtf8(StringPiece16(str16, len)); 255ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 256ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->attributes.push_back(std::move(attr)); 25775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 258ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 25975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 26075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 261ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len, 262ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski IDiagnostics* diag, const Source& source) { 263ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // We import the android namespace because on Windows NO_ERROR is a macro, not 264ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // an enum, which 265ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // causes errors when qualifying it with android:: 266ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski using namespace android; 267803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski 268ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Node> root; 269ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::stack<Node*> node_stack; 27075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 271ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResXMLTree tree; 272ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (tree.setTo(data, data_len) != NO_ERROR) { 273ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 274ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 275ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 276ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResXMLParser::event_code_t code; 277ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT && 278ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski code != ResXMLParser::END_DOCUMENT) { 279ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Node> new_node; 280ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski switch (code) { 281ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::START_NAMESPACE: { 282ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Namespace> node = util::make_unique<Namespace>(); 283ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t len; 284ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char16_t* str16 = tree.getNamespacePrefix(&len); 285ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 286ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->namespace_prefix = util::Utf16ToUtf8(StringPiece16(str16, len)); 287ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 288ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 289ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str16 = tree.getNamespaceUri(&len); 290ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 291ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len)); 292ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 293ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski new_node = std::move(node); 294ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 295ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 296ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 297ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::START_TAG: { 298ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Element> node = util::make_unique<Element>(); 299ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t len; 300ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char16_t* str16 = tree.getElementNamespace(&len); 301ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 302ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len)); 303ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 30475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 305ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str16 = tree.getElementName(&len); 306ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 307ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->name = util::Utf16ToUtf8(StringPiece16(str16, len)); 30875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 30975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 310ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CopyAttributes(node.get(), &tree); 311ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 312ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski new_node = std::move(node); 313ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 314ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 315ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 316ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::TEXT: { 317ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Text> node = util::make_unique<Text>(); 318ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t len; 319ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char16_t* str16 = tree.getText(&len); 320ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 321ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->text = util::Utf16ToUtf8(StringPiece16(str16, len)); 32275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 323ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski new_node = std::move(node); 324ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 325ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 326ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 327ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::END_NAMESPACE: 328ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::END_TAG: 329ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(!node_stack.empty()); 330ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node_stack.pop(); 331ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 332ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 333ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski default: 334ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski LOG(FATAL) << "unhandled XML chunk type"; 335ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 33675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 33775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 338ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (new_node) { 339ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski new_node->line_number = tree.getLineNumber(); 340ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 341ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Node* this_node = new_node.get(); 342ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!root) { 343ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(node_stack.empty()) << "node stack should be empty"; 344ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski root = std::move(new_node); 345ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else { 346ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(!node_stack.empty()) << "node stack should not be empty"; 347e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski node_stack.top()->AppendChild(std::move(new_node)); 348ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 349ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 350ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!NodeCast<Text>(this_node)) { 351ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node_stack.push(this_node); 352ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 3535eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski } 354ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 355ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return util::make_unique<XmlResource>(ResourceFile{}, std::move(root)); 3565eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski} 3575eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 358ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<Node> Namespace::Clone() { 359ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto ns = util::make_unique<Namespace>(); 360ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->comment = comment; 361ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->line_number = line_number; 362ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->column_number = column_number; 363ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->namespace_prefix = namespace_prefix; 364ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->namespace_uri = namespace_uri; 365ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 366ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->children.reserve(children.size()); 367ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::unique_ptr<xml::Node>& child : children) { 368e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski ns->AppendChild(child->Clone()); 369ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 370ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return std::move(ns); 371467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 372467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 373ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* FindRootElement(XmlResource* doc) { 374ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return FindRootElement(doc->root.get()); 375ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski} 376ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 377ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* FindRootElement(Node* node) { 378ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!node) { 379ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return nullptr; 380ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 381ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 382ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Element* el = nullptr; 383ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while ((el = NodeCast<Element>(node)) == nullptr) { 384ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (node->children.empty()) { 385ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return nullptr; 386ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 387ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // We are looking for the first element, and namespaces can only have one 388ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // child. 389ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node = node->children.front().get(); 390ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 391ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return el; 392ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 393ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 394e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinskivoid Node::AppendChild(std::unique_ptr<Node> child) { 395ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski child->parent = this; 396ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski children.push_back(std::move(child)); 39775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 39875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 399e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinskivoid Node::InsertChild(size_t index, std::unique_ptr<Node> child) { 400e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski child->parent = this; 401e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski children.insert(children.begin() + index, std::move(child)); 402e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski} 403e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski 404ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiAttribute* Element::FindAttribute(const StringPiece& ns, 405ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& name) { 406ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto& attr : attributes) { 407ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (ns == attr.namespace_uri && name == attr.name) { 408ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return &attr; 40975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 410ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 411ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return nullptr; 41275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 41375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 414ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* Element::FindChild(const StringPiece& ns, const StringPiece& name) { 415ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return FindChildWithAttribute(ns, name, {}, {}, {}); 41675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 41775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 418ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* Element::FindChildWithAttribute(const StringPiece& ns, 419ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& name, 420ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& attr_ns, 421ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& attr_name, 422ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& attr_value) { 423ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto& child_node : children) { 424ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Node* child = child_node.get(); 425ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while (NodeCast<Namespace>(child)) { 426ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (child->children.empty()) { 427ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 428ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 429ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski child = child->children[0].get(); 43075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 43175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 432ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (Element* el = NodeCast<Element>(child)) { 433ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (ns == el->namespace_uri && name == el->name) { 434ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (attr_ns.empty() && attr_name.empty()) { 435ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return el; 43675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 43775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 438ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = el->FindAttribute(attr_ns, attr_name); 439ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (attr && attr_value == attr->value) { 440ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return el; 44175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 442ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 44375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 444ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 445ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return nullptr; 44675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 44775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 448ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::vector<Element*> Element::GetChildElements() { 449ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<Element*> elements; 450ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto& child_node : children) { 451ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Node* child = child_node.get(); 452ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while (NodeCast<Namespace>(child)) { 453ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (child->children.empty()) { 454ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 455ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 456ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski child = child->children[0].get(); 4575eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski } 4585eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 459ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (Element* el = NodeCast<Element>(child)) { 460ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski elements.push_back(el); 4615eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski } 462ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 463ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return elements; 4645eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski} 4655eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 466ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<Node> Element::Clone() { 467ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto el = util::make_unique<Element>(); 468ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->comment = comment; 469ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->line_number = line_number; 470ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->column_number = column_number; 471ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->name = name; 472ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->namespace_uri = namespace_uri; 473ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 474ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->attributes.reserve(attributes.size()); 475ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (xml::Attribute& attr : attributes) { 476ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // Don't copy compiled values or attributes. 477ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->attributes.push_back( 478ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski xml::Attribute{attr.namespace_uri, attr.name, attr.value}); 479ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 480ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 481ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->children.reserve(children.size()); 482ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::unique_ptr<xml::Node>& child : children) { 483e343eb145c42d00c4fd3fdde93cd0be55cb5b855Adam Lesinski el->AppendChild(child->Clone()); 484ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 485ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return std::move(el); 4865eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski} 4875eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 488ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<Node> Text::Clone() { 489ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto t = util::make_unique<Text>(); 490ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski t->comment = comment; 491ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski t->line_number = line_number; 492ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski t->column_number = column_number; 493ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski t->text = text; 494ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return std::move(t); 495ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski} 496467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 497ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskivoid PackageAwareVisitor::Visit(Namespace* ns) { 498ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool added = false; 499ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (Maybe<ExtractedPackage> maybe_package = 500ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ExtractPackageFromNamespace(ns->namespace_uri)) { 501ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ExtractedPackage& package = maybe_package.value(); 502ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski package_decls_.push_back( 503ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski PackageDecl{ns->namespace_prefix, std::move(package)}); 504ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski added = true; 505ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 506ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 507ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Visitor::Visit(ns); 508ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 509ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (added) { 510ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski package_decls_.pop_back(); 511ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 512467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 513467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 514ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiMaybe<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias( 515ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& alias, const StringPiece& local_package) const { 516ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (alias.empty()) { 517d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski return ExtractedPackage{local_package.to_string(), false /* private */}; 518ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 519ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 520ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const auto rend = package_decls_.rend(); 521ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) { 522ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (alias == iter->prefix) { 523ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (iter->package.package.empty()) { 524d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski return ExtractedPackage{local_package.to_string(), iter->package.private_namespace}; 525ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 526ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return iter->package; 527ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 528ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 529ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 530467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 531467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 532ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski} // namespace xml 533ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski} // namespace aapt 534