XmlDom.cpp revision ce5e56e243d262a9b65459c3bd0bb9eaadd40628
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 21ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <cassert> 2275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <memory> 2375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <stack> 2475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <string> 2575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <tuple> 2675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 27ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "android-base/logging.h" 28ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 29ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "XmlPullParser.h" 30ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include "util/Util.h" 31ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 3275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace aapt { 3375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace xml { 3475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 3575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskiconstexpr char kXmlNamespaceSep = 1; 3675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 3775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistruct Stack { 38ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<xml::Node> root; 39ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::stack<xml::Node*> node_stack; 40ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string pending_comment; 4175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}; 4275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 4375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/** 4475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Extracts the namespace and name of an expanded element or attribute name. 4575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */ 46ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void SplitName(const char* name, std::string* out_ns, 47ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::string* out_name) { 48ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char* p = name; 49ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while (*p != 0 && *p != kXmlNamespaceSep) { 50ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski p++; 51ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 52ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 53ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (*p == 0) { 54ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski out_ns->clear(); 55ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski *out_name = StringPiece(name).ToString(); 56ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else { 57ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski *out_ns = StringPiece(name, (p - name)).ToString(); 58ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski *out_name = StringPiece(p + 1).ToString(); 59ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 6075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 6175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 62ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void AddToStack(Stack* stack, XML_Parser parser, 63ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Node> node) { 64ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->line_number = XML_GetCurrentLineNumber(parser); 65ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->column_number = XML_GetCurrentColumnNumber(parser); 66ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 67ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Node* this_node = node.get(); 68ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!stack->node_stack.empty()) { 69ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->node_stack.top()->AddChild(std::move(node)); 70ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else { 71ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->root = std::move(node); 72ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 73ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 74ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!NodeCast<Text>(this_node)) { 75ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->node_stack.push(this_node); 76ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 7775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 7875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix, 80ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char* uri) { 81ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 82ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 8375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 84ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Namespace> ns = util::make_unique<Namespace>(); 85ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (prefix) { 86ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->namespace_prefix = StringPiece(prefix).ToString(); 87ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 8875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 89ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (uri) { 90ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->namespace_uri = StringPiece(uri).ToString(); 91ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 9275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 93ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski AddToStack(stack, parser, std::move(ns)); 9475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 9575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 96ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL EndNamespaceHandler(void* user_data, const char* prefix) { 97ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 98ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 9975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 100ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(!stack->node_stack.empty()); 101ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->node_stack.pop(); 10275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 10375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 104ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic bool less_attribute(const Attribute& lhs, const Attribute& rhs) { 105ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return std::tie(lhs.namespace_uri, lhs.name, lhs.value) < 106ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::tie(rhs.namespace_uri, rhs.name, rhs.value); 10775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 10875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 109ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL StartElementHandler(void* user_data, const char* name, 110ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char** attrs) { 111ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 112ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 11375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 114ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Element> el = util::make_unique<Element>(); 115ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski SplitName(name, &el->namespace_uri, &el->name); 11675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 117ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while (*attrs) { 118ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute attribute; 119ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski SplitName(*attrs++, &attribute.namespace_uri, &attribute.name); 120ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attribute.value = StringPiece(*attrs++).ToString(); 12175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 122ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // Insert in sorted order. 123ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto iter = std::lower_bound(el->attributes.begin(), el->attributes.end(), 124ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attribute, less_attribute); 125ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->attributes.insert(iter, std::move(attribute)); 126ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 12775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 128ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->comment = std::move(stack->pending_comment); 129ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski AddToStack(stack, parser, std::move(el)); 13075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 13175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 132ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL EndElementHandler(void* user_data, const char* name) { 133ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 134ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 13575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 136ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(!stack->node_stack.empty()); 137ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // stack->nodeStack.top()->comment = std::move(stack->pendingComment); 138ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->node_stack.pop(); 13975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 14075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 141ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL CharacterDataHandler(void* user_data, const char* s, 142ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski int len) { 143ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 145ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 146ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!s || len <= 0) { 147ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return; 148ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 149ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 150ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // See if we can just append the text to a previous text node. 151ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!stack->node_stack.empty()) { 152ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Node* currentParent = stack->node_stack.top(); 153ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!currentParent->children.empty()) { 154ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Node* last_child = currentParent->children.back().get(); 155ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (Text* text = NodeCast<Text>(last_child)) { 156ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski text->text += StringPiece(s, len).ToString(); 15775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return; 158ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 15975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 160ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 16175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 162ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Text> text = util::make_unique<Text>(); 163ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski text->text = StringPiece(s, len).ToString(); 164ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski AddToStack(stack, parser, std::move(text)); 16575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 16675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 167ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void XMLCALL CommentDataHandler(void* user_data, const char* comment) { 168ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(user_data); 169ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 17075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 171ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!stack->pending_comment.empty()) { 172ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->pending_comment += '\n'; 173ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 174ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack->pending_comment += comment; 17575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 17675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 177ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<XmlResource> Inflate(std::istream* in, IDiagnostics* diag, 178ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const Source& source) { 179ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Stack stack; 180ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 181ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_Parser parser = XML_ParserCreateNS(nullptr, kXmlNamespaceSep); 182ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_SetUserData(parser, &stack); 183ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_UseParserAsHandlerArg(parser); 184ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_SetElementHandler(parser, StartElementHandler, EndElementHandler); 185ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_SetNamespaceDeclHandler(parser, StartNamespaceHandler, 186ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski EndNamespaceHandler); 187ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_SetCharacterDataHandler(parser, CharacterDataHandler); 188ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_SetCommentHandler(parser, CommentDataHandler); 189ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 190ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski char buffer[1024]; 191ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while (!in->eof()) { 192ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski in->read(buffer, sizeof(buffer) / sizeof(buffer[0])); 193ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (in->bad() && !in->eof()) { 194ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack.root = {}; 195ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(source) << strerror(errno)); 196ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 19775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 19875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 199ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (XML_Parse(parser, buffer, in->gcount(), in->eof()) == 200ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_STATUS_ERROR) { 201ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski stack.root = {}; 202ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski diag->Error(DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser))) 203ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski << XML_ErrorString(XML_GetErrorCode(parser))); 204ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 2051ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 206ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 207ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 208ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski XML_ParserFree(parser); 209ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (stack.root) { 210ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return util::make_unique<XmlResource>(ResourceFile{{}, {}, source}, 211ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::move(stack.root)); 212ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 213ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 21475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 21575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 216ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistatic void CopyAttributes(Element* el, android::ResXMLParser* parser) { 217ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const size_t attr_count = parser->getAttributeCount(); 218ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (attr_count > 0) { 219ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->attributes.reserve(attr_count); 220ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (size_t i = 0; i < attr_count; i++) { 221ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute attr; 222ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t len; 223ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char16_t* str16 = parser->getAttributeNamespace(i, &len); 224ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 225ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr.namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len)); 226ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 227ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 228ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str16 = parser->getAttributeName(i, &len); 229ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 230ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr.name = util::Utf16ToUtf8(StringPiece16(str16, len)); 231ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 232ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 233ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str16 = parser->getAttributeStringValue(i, &len); 234ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 235ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski attr.value = util::Utf16ToUtf8(StringPiece16(str16, len)); 236ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 237ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->attributes.push_back(std::move(attr)); 23875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 239ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 24075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 24175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 242ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<XmlResource> Inflate(const void* data, size_t data_len, 243ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski IDiagnostics* diag, const Source& source) { 244ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // We import the android namespace because on Windows NO_ERROR is a macro, not 245ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // an enum, which 246ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // causes errors when qualifying it with android:: 247ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski using namespace android; 248803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski 249ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Node> root; 250ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::stack<Node*> node_stack; 25175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 252ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResXMLTree tree; 253ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (tree.setTo(data, data_len) != NO_ERROR) { 254ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 255ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 256ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 257ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ResXMLParser::event_code_t code; 258ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT && 259ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski code != ResXMLParser::END_DOCUMENT) { 260ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Node> new_node; 261ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski switch (code) { 262ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::START_NAMESPACE: { 263ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Namespace> node = util::make_unique<Namespace>(); 264ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t len; 265ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char16_t* str16 = tree.getNamespacePrefix(&len); 266ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 267ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->namespace_prefix = util::Utf16ToUtf8(StringPiece16(str16, len)); 268ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 269ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 270ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str16 = tree.getNamespaceUri(&len); 271ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 272ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len)); 273ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 274ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski new_node = std::move(node); 275ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 276ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 277ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 278ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::START_TAG: { 279ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Element> node = util::make_unique<Element>(); 280ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t len; 281ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char16_t* str16 = tree.getElementNamespace(&len); 282ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 283ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->namespace_uri = util::Utf16ToUtf8(StringPiece16(str16, len)); 284ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 28575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 286ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski str16 = tree.getElementName(&len); 287ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 288ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->name = util::Utf16ToUtf8(StringPiece16(str16, len)); 28975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 29075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 291ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CopyAttributes(node.get(), &tree); 292ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 293ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski new_node = std::move(node); 294ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 295ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 296ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 297ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::TEXT: { 298ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<Text> node = util::make_unique<Text>(); 299ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski size_t len; 300ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const char16_t* str16 = tree.getText(&len); 301ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (str16) { 302ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node->text = util::Utf16ToUtf8(StringPiece16(str16, len)); 30375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 304ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski new_node = std::move(node); 305ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 306ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 307ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 308ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::END_NAMESPACE: 309ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski case ResXMLParser::END_TAG: 310ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(!node_stack.empty()); 311ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node_stack.pop(); 312ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 313ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 314ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski default: 315ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski LOG(FATAL) << "unhandled XML chunk type"; 316ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 31775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 31875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 319ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (new_node) { 320ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski new_node->line_number = tree.getLineNumber(); 321ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 322ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Node* this_node = new_node.get(); 323ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!root) { 324ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(node_stack.empty()) << "node stack should be empty"; 325ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski root = std::move(new_node); 326ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } else { 327ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski CHECK(!node_stack.empty()) << "node stack should not be empty"; 328ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node_stack.top()->AddChild(std::move(new_node)); 329ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 330ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 331ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!NodeCast<Text>(this_node)) { 332ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node_stack.push(this_node); 333ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 3345eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski } 335ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 336ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return util::make_unique<XmlResource>(ResourceFile{}, std::move(root)); 3375eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski} 3385eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 339ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<Node> Namespace::Clone() { 340ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto ns = util::make_unique<Namespace>(); 341ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->comment = comment; 342ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->line_number = line_number; 343ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->column_number = column_number; 344ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->namespace_prefix = namespace_prefix; 345ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->namespace_uri = namespace_uri; 346ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 347ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->children.reserve(children.size()); 348ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::unique_ptr<xml::Node>& child : children) { 349ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ns->AddChild(child->Clone()); 350ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 351ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return std::move(ns); 352467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 353467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 354ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* FindRootElement(XmlResource* doc) { 355ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return FindRootElement(doc->root.get()); 356ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski} 357ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 358ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* FindRootElement(Node* node) { 359ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!node) { 360ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return nullptr; 361ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 362ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 363ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Element* el = nullptr; 364ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while ((el = NodeCast<Element>(node)) == nullptr) { 365ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (node->children.empty()) { 366ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return nullptr; 367ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 368ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // We are looking for the first element, and namespaces can only have one 369ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // child. 370ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski node = node->children.front().get(); 371ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 372ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return el; 373ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 374ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 375ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskivoid Node::AddChild(std::unique_ptr<Node> child) { 376ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski child->parent = this; 377ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski children.push_back(std::move(child)); 37875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 37975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 380ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiAttribute* Element::FindAttribute(const StringPiece& ns, 381ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& name) { 382ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto& attr : attributes) { 383ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (ns == attr.namespace_uri && name == attr.name) { 384ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return &attr; 38575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 386ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 387ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return nullptr; 38875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 38975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 390ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* Element::FindChild(const StringPiece& ns, const StringPiece& name) { 391ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return FindChildWithAttribute(ns, name, {}, {}, {}); 39275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 39375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 394ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiElement* Element::FindChildWithAttribute(const StringPiece& ns, 395ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& name, 396ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& attr_ns, 397ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& attr_name, 398ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& attr_value) { 399ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto& child_node : children) { 400ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Node* child = child_node.get(); 401ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while (NodeCast<Namespace>(child)) { 402ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (child->children.empty()) { 403ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 404ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 405ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski child = child->children[0].get(); 40675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 40775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 408ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (Element* el = NodeCast<Element>(child)) { 409ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (ns == el->namespace_uri && name == el->name) { 410ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (attr_ns.empty() && attr_name.empty()) { 411ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return el; 41275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 41375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 414ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Attribute* attr = el->FindAttribute(attr_ns, attr_name); 415ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (attr && attr_value == attr->value) { 416ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return el; 41775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 418ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 41975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 420ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 421ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return nullptr; 42275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 42375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 424ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::vector<Element*> Element::GetChildElements() { 425ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::vector<Element*> elements; 426ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto& child_node : children) { 427ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Node* child = child_node.get(); 428ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski while (NodeCast<Namespace>(child)) { 429ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (child->children.empty()) { 430ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski break; 431ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 432ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski child = child->children[0].get(); 4335eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski } 4345eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 435ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (Element* el = NodeCast<Element>(child)) { 436ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski elements.push_back(el); 4375eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski } 438ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 439ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return elements; 4405eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski} 4415eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 442ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<Node> Element::Clone() { 443ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto el = util::make_unique<Element>(); 444ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->comment = comment; 445ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->line_number = line_number; 446ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->column_number = column_number; 447ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->name = name; 448ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->namespace_uri = namespace_uri; 449ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 450ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->attributes.reserve(attributes.size()); 451ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (xml::Attribute& attr : attributes) { 452ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski // Don't copy compiled values or attributes. 453ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->attributes.push_back( 454ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski xml::Attribute{attr.namespace_uri, attr.name, attr.value}); 455ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 456ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 457ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->children.reserve(children.size()); 458ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::unique_ptr<xml::Node>& child : children) { 459ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski el->AddChild(child->Clone()); 460ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 461ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return std::move(el); 4625eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski} 4635eeaaddffd23d8d85aeb321e3ceea626e42cf9deAdam Lesinski 464ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskistd::unique_ptr<Node> Text::Clone() { 465ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski auto t = util::make_unique<Text>(); 466ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski t->comment = comment; 467ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski t->line_number = line_number; 468ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski t->column_number = column_number; 469ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski t->text = text; 470ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return std::move(t); 471ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski} 472467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 473ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskivoid PackageAwareVisitor::Visit(Namespace* ns) { 474ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool added = false; 475ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (Maybe<ExtractedPackage> maybe_package = 476ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ExtractPackageFromNamespace(ns->namespace_uri)) { 477ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski ExtractedPackage& package = maybe_package.value(); 478ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski package_decls_.push_back( 479ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski PackageDecl{ns->namespace_prefix, std::move(package)}); 480ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski added = true; 481ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 482ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 483ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Visitor::Visit(ns); 484ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 485ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (added) { 486ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski package_decls_.pop_back(); 487ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 488467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 489467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 490ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiMaybe<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias( 491ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const StringPiece& alias, const StringPiece& local_package) const { 492ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (alias.empty()) { 493ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return ExtractedPackage{local_package.ToString(), false /* private */}; 494ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 495ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 496ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const auto rend = package_decls_.rend(); 497ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) { 498ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (alias == iter->prefix) { 499ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (iter->package.package.empty()) { 500ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return ExtractedPackage{local_package.ToString(), 501ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski iter->package.private_namespace}; 502ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 503ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return iter->package; 504ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 505ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski } 506ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski return {}; 507467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 508467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 509ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski} // namespace xml 510ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski} // namespace aapt 511