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#include "XmlPullParser.h" 19467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "util/Util.h" 2075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 2175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <cassert> 22467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include <expat.h> 2375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <memory> 2475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <stack> 2575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <string> 2675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <tuple> 2775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 2875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace aapt { 2975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace xml { 3075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 3175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskiconstexpr char kXmlNamespaceSep = 1; 3275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 3375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistruct Stack { 3475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<xml::Node> root; 3575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::stack<xml::Node*> nodeStack; 3675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::u16string pendingComment; 3775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}; 3875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 3975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/** 4075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Extracts the namespace and name of an expanded element or attribute name. 4175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */ 4275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void splitName(const char* name, std::u16string* outNs, std::u16string* outName) { 4375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski const char* p = name; 4475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski while (*p != 0 && *p != kXmlNamespaceSep) { 4575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski p++; 4675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 4775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 4875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (*p == 0) { 4975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski outNs->clear(); 5075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski *outName = util::utf8ToUtf16(name); 5175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } else { 5275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski *outNs = util::utf8ToUtf16(StringPiece(name, (p - name))); 5375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski *outName = util::utf8ToUtf16(p + 1); 5475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 5575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 5675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 5775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void addToStack(Stack* stack, XML_Parser parser, std::unique_ptr<Node> node) { 5875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski node->lineNumber = XML_GetCurrentLineNumber(parser); 5975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski node->columnNumber = XML_GetCurrentColumnNumber(parser); 6075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 6175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Node* thisNode = node.get(); 6275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (!stack->nodeStack.empty()) { 6375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack->nodeStack.top()->addChild(std::move(node)); 6475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } else { 6575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack->root = std::move(node); 6675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 6775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (!nodeCast<Text>(thisNode)) { 6975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack->nodeStack.push(thisNode); 7075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 7175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 7275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 7375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void XMLCALL startNamespaceHandler(void* userData, const char* prefix, const char* uri) { 7475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(userData); 7575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 7675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 7775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Namespace> ns = util::make_unique<Namespace>(); 7875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (prefix) { 7975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski ns->namespacePrefix = util::utf8ToUtf16(prefix); 8075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 8175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 8275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (uri) { 8375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski ns->namespaceUri = util::utf8ToUtf16(uri); 8475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 8575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 8675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski addToStack(stack, parser, std::move(ns)); 8775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 8875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 8975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void XMLCALL endNamespaceHandler(void* userData, const char* prefix) { 9075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(userData); 9175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 9275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 9375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski assert(!stack->nodeStack.empty()); 9475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack->nodeStack.pop(); 9575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 9675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 9775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic bool lessAttribute(const Attribute& lhs, const Attribute& rhs) { 9875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return std::tie(lhs.namespaceUri, lhs.name, lhs.value) < 9975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::tie(rhs.namespaceUri, rhs.name, rhs.value); 10075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 10175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 10275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void XMLCALL startElementHandler(void* userData, const char* name, const char** attrs) { 10375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(userData); 10475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 10575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 10675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Element> el = util::make_unique<Element>(); 10775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski splitName(name, &el->namespaceUri, &el->name); 10875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 10975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski while (*attrs) { 11075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Attribute attribute; 11175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski splitName(*attrs++, &attribute.namespaceUri, &attribute.name); 11275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski attribute.value = util::utf8ToUtf16(*attrs++); 11375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 11475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski // Insert in sorted order. 11575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski auto iter = std::lower_bound(el->attributes.begin(), el->attributes.end(), attribute, 11675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski lessAttribute); 11775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->attributes.insert(iter, std::move(attribute)); 11875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 11975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 12075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->comment = std::move(stack->pendingComment); 12175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski addToStack(stack, parser, std::move(el)); 12275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 12375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 12475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void XMLCALL endElementHandler(void* userData, const char* name) { 12575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(userData); 12675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 12775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 12875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski assert(!stack->nodeStack.empty()); 129ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski //stack->nodeStack.top()->comment = std::move(stack->pendingComment); 13075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack->nodeStack.pop(); 13175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 13275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 13375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void XMLCALL characterDataHandler(void* userData, const char* s, int len) { 13475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(userData); 13575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 13675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 13775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (!s || len <= 0) { 13875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return; 13975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 14075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 14175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski // See if we can just append the text to a previous text node. 14275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (!stack->nodeStack.empty()) { 14375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Node* currentParent = stack->nodeStack.top(); 14475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (!currentParent->children.empty()) { 14575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Node* lastChild = currentParent->children.back().get(); 1461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (Text* text = nodeCast<Text>(lastChild)) { 14775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski text->text += util::utf8ToUtf16(StringPiece(s, len)); 14875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return; 14975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 15075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 15175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 15275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 15375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Text> text = util::make_unique<Text>(); 15475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski text->text = util::utf8ToUtf16(StringPiece(s, len)); 15575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski addToStack(stack, parser, std::move(text)); 15675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 15775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 15875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void XMLCALL commentDataHandler(void* userData, const char* comment) { 15975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(userData); 16075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 16175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 16275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (!stack->pendingComment.empty()) { 16375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack->pendingComment += '\n'; 16475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 16575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack->pendingComment += util::utf8ToUtf16(comment); 16675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 16775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 1681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistd::unique_ptr<XmlResource> inflate(std::istream* in, IDiagnostics* diag, const Source& source) { 16975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Stack stack; 17075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 17175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_Parser parser = XML_ParserCreateNS(nullptr, kXmlNamespaceSep); 17275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_SetUserData(parser, &stack); 17375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_UseParserAsHandlerArg(parser); 17475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_SetElementHandler(parser, startElementHandler, endElementHandler); 17575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_SetNamespaceDeclHandler(parser, startNamespaceHandler, endNamespaceHandler); 17675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_SetCharacterDataHandler(parser, characterDataHandler); 17775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_SetCommentHandler(parser, commentDataHandler); 17875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 17975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski char buffer[1024]; 18075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski while (!in->eof()) { 18175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski in->read(buffer, sizeof(buffer) / sizeof(buffer[0])); 18275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (in->bad() && !in->eof()) { 18375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack.root = {}; 1841ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski diag->error(DiagMessage(source) << strerror(errno)); 18575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 18675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 18775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 18875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (XML_Parse(parser, buffer, in->gcount(), in->eof()) == XML_STATUS_ERROR) { 18975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack.root = {}; 1901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski diag->error(DiagMessage(source.withLine(XML_GetCurrentLineNumber(parser))) 1911ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << XML_ErrorString(XML_GetErrorCode(parser))); 19275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 19375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 19475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 19575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 19675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_ParserFree(parser); 1971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (stack.root) { 198ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski return util::make_unique<XmlResource>(ResourceFile{ {}, {}, source }, std::move(stack.root)); 1991ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 2001ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return {}; 20175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 20275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 20375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void copyAttributes(Element* el, android::ResXMLParser* parser) { 20475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski const size_t attrCount = parser->getAttributeCount(); 20575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (attrCount > 0) { 20675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->attributes.reserve(attrCount); 20775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski for (size_t i = 0; i < attrCount; i++) { 20875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Attribute attr; 20975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski size_t len; 21075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski const char16_t* str16 = parser->getAttributeNamespace(i, &len); 21175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 21275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski attr.namespaceUri.assign(str16, len); 21375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 21475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 21575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski str16 = parser->getAttributeName(i, &len); 21675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 21775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski attr.name.assign(str16, len); 21875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 21975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 22075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski str16 = parser->getAttributeStringValue(i, &len); 22175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 22275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski attr.value.assign(str16, len); 22375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 22475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->attributes.push_back(std::move(attr)); 22575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 22675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 22775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 22875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 2291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistd::unique_ptr<XmlResource> inflate(const void* data, size_t dataLen, IDiagnostics* diag, 2301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski const Source& source) { 231803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski // We import the android namespace because on Windows NO_ERROR is a macro, not an enum, which 232803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski // causes errors when qualifying it with android:: 233803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski using namespace android; 234803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski 23575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Node> root; 23675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::stack<Node*> nodeStack; 23775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 238803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski ResXMLTree tree; 239803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski if (tree.setTo(data, dataLen) != NO_ERROR) { 24075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return {}; 24175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 24275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 243803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski ResXMLParser::event_code_t code; 244803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT && 245803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski code != ResXMLParser::END_DOCUMENT) { 24675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Node> newNode; 24775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski switch (code) { 248803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski case ResXMLParser::START_NAMESPACE: { 24975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Namespace> node = util::make_unique<Namespace>(); 25075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski size_t len; 25175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski const char16_t* str16 = tree.getNamespacePrefix(&len); 25275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 25375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski node->namespacePrefix.assign(str16, len); 25475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 25575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 25675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski str16 = tree.getNamespaceUri(&len); 25775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 25875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski node->namespaceUri.assign(str16, len); 25975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 26075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski newNode = std::move(node); 26175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 26275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 26375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 264803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski case ResXMLParser::START_TAG: { 26575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Element> node = util::make_unique<Element>(); 26675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski size_t len; 26775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski const char16_t* str16 = tree.getElementNamespace(&len); 26875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 26975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski node->namespaceUri.assign(str16, len); 27075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 27175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 27275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski str16 = tree.getElementName(&len); 27375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 27475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski node->name.assign(str16, len); 27575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 27675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 27775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski copyAttributes(node.get(), &tree); 27875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 27975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski newNode = std::move(node); 28075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 28175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 28275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 283803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski case ResXMLParser::TEXT: { 28475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Text> node = util::make_unique<Text>(); 28575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski size_t len; 28675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski const char16_t* str16 = tree.getText(&len); 28775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 28875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski node->text.assign(str16, len); 28975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 29075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski newNode = std::move(node); 29175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 29275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 29375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 294803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski case ResXMLParser::END_NAMESPACE: 295803c7c807969bea1f1c50f348832f5b60ad05d8eAdam Lesinski case ResXMLParser::END_TAG: 29675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski assert(!nodeStack.empty()); 29775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski nodeStack.pop(); 29875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 29975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 30075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski default: 30175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski assert(false); 30275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 30375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 30475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 30575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (newNode) { 30675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski newNode->lineNumber = tree.getLineNumber(); 30775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 30875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Node* thisNode = newNode.get(); 30975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (!root) { 31075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski assert(nodeStack.empty()); 31175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski root = std::move(newNode); 31275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } else { 31375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski assert(!nodeStack.empty()); 31475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski nodeStack.top()->addChild(std::move(newNode)); 31575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 31675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 3171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (!nodeCast<Text>(thisNode)) { 31875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski nodeStack.push(thisNode); 31975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 32075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 32175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 3221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return util::make_unique<XmlResource>(ResourceFile{}, std::move(root)); 32375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 32475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 325467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam LesinskiElement* findRootElement(XmlResource* doc) { 326467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return findRootElement(doc->root.get()); 327467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 328467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 329ca5638fd85098c3d0a699492751043545f75553aAdam LesinskiElement* findRootElement(Node* node) { 330ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski if (!node) { 331ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski return nullptr; 332ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 333ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 334ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski Element* el = nullptr; 335ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski while ((el = nodeCast<Element>(node)) == nullptr) { 336ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski if (node->children.empty()) { 337ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski return nullptr; 338ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 339ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski // We are looking for the first element, and namespaces can only have one child. 340ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski node = node->children.front().get(); 341ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 342ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski return el; 343ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 344ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 34575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskivoid Node::addChild(std::unique_ptr<Node> child) { 34675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski child->parent = this; 34775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski children.push_back(std::move(child)); 34875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 34975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 35075f3a55cc569a9b61f540a85d9828e91bdca5047Adam LesinskiAttribute* Element::findAttribute(const StringPiece16& ns, const StringPiece16& name) { 35175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski for (auto& attr : attributes) { 35275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (ns == attr.namespaceUri && name == attr.name) { 35375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return &attr; 35475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 35575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 35675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return nullptr; 35775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 35875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 35975f3a55cc569a9b61f540a85d9828e91bdca5047Adam LesinskiElement* Element::findChild(const StringPiece16& ns, const StringPiece16& name) { 3601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return findChildWithAttribute(ns, name, {}, {}, {}); 36175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 36275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 36375f3a55cc569a9b61f540a85d9828e91bdca5047Adam LesinskiElement* Element::findChildWithAttribute(const StringPiece16& ns, const StringPiece16& name, 3641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski const StringPiece16& attrNs, const StringPiece16& attrName, 3651ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski const StringPiece16& attrValue) { 36675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski for (auto& childNode : children) { 36775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Node* child = childNode.get(); 3681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski while (nodeCast<Namespace>(child)) { 36975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (child->children.empty()) { 37075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 37175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 37275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski child = child->children[0].get(); 37375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 37475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 3751ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (Element* el = nodeCast<Element>(child)) { 37675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (ns == el->namespaceUri && name == el->name) { 3771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (attrNs.empty() && attrName.empty()) { 37875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return el; 37975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 38075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 3811ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* attr = el->findAttribute(attrNs, attrName); 3821ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (attr && attrValue == attr->value) { 38375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return el; 38475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 38575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 38675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 38775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 38875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return nullptr; 38975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 39075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 39175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistd::vector<Element*> Element::getChildElements() { 39275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::vector<Element*> elements; 39375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski for (auto& childNode : children) { 39475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Node* child = childNode.get(); 3951ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski while (nodeCast<Namespace>(child)) { 39675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (child->children.empty()) { 39775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 39875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 39975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski child = child->children[0].get(); 40075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 40175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 4021ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (Element* el = nodeCast<Element>(child)) { 4031ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski elements.push_back(el); 40475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 40575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 40675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return elements; 40775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 40875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 409467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinskivoid PackageAwareVisitor::visit(Namespace* ns) { 410467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski bool added = false; 411467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (Maybe<ExtractedPackage> maybePackage = extractPackageFromNamespace(ns->namespaceUri)) { 412467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski ExtractedPackage& package = maybePackage.value(); 413467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski mPackageDecls.push_back(PackageDecl{ ns->namespacePrefix, std::move(package) }); 414467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski added = true; 415467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 416467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 417467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski Visitor::visit(ns); 418467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 419467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (added) { 420467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski mPackageDecls.pop_back(); 421467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 422467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 423467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 424467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam LesinskiMaybe<ExtractedPackage> PackageAwareVisitor::transformPackageAlias( 425467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski const StringPiece16& alias, const StringPiece16& localPackage) const { 426467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (alias.empty()) { 427467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return ExtractedPackage{ localPackage.toString(), false /* private */ }; 428467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 429467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 430467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski const auto rend = mPackageDecls.rend(); 431467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski for (auto iter = mPackageDecls.rbegin(); iter != rend; ++iter) { 432467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (alias == iter->prefix) { 433467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski if (iter->package.package.empty()) { 434467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return ExtractedPackage{ localPackage.toString(), 435467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski iter->package.privateNamespace }; 436467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 437467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return iter->package; 438467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 439467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski } 440467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski return {}; 441467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} 442467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski 44375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} // namespace xml 44475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} // namespace aapt 445