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