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 "Logger.h" 1875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include "Util.h" 1975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include "XmlDom.h" 2075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include "XmlPullParser.h" 2175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 2275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <cassert> 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 6875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (thisNode->type != NodeType::kText) { 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()); 12975f3a55cc569a9b61f540a85d9828e91bdca5047Adam 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(); 14675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (lastChild->type == NodeType::kText) { 14775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Text* text = static_cast<Text*>(lastChild); 14875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski text->text += util::utf8ToUtf16(StringPiece(s, len)); 14975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return; 15075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 15175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 15275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 15375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 15475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Text> text = util::make_unique<Text>(); 15575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski text->text = util::utf8ToUtf16(StringPiece(s, len)); 15675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski addToStack(stack, parser, std::move(text)); 15775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 15875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 15975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void XMLCALL commentDataHandler(void* userData, const char* comment) { 16075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(userData); 16175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 16275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 16375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (!stack->pendingComment.empty()) { 16475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack->pendingComment += '\n'; 16575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 16675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack->pendingComment += util::utf8ToUtf16(comment); 16775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 16875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 16975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistd::unique_ptr<Node> inflate(std::istream* in, SourceLogger* logger) { 17075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Stack stack; 17175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 17275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_Parser parser = XML_ParserCreateNS(nullptr, kXmlNamespaceSep); 17375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_SetUserData(parser, &stack); 17475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_UseParserAsHandlerArg(parser); 17575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_SetElementHandler(parser, startElementHandler, endElementHandler); 17675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_SetNamespaceDeclHandler(parser, startNamespaceHandler, endNamespaceHandler); 17775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_SetCharacterDataHandler(parser, characterDataHandler); 17875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_SetCommentHandler(parser, commentDataHandler); 17975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 18075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski char buffer[1024]; 18175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski while (!in->eof()) { 18275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski in->read(buffer, sizeof(buffer) / sizeof(buffer[0])); 18375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (in->bad() && !in->eof()) { 18475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack.root = {}; 18575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski logger->error() << strerror(errno) << std::endl; 18675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 18775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 18875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 18975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (XML_Parse(parser, buffer, in->gcount(), in->eof()) == XML_STATUS_ERROR) { 19075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack.root = {}; 19175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski logger->error(XML_GetCurrentLineNumber(parser)) 19275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski << XML_ErrorString(XML_GetErrorCode(parser)) << std::endl; 19375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 19475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 19575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 19675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 19775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_ParserFree(parser); 19875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return std::move(stack.root); 19975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 20075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 20175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void copyAttributes(Element* el, android::ResXMLParser* parser) { 20275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski const size_t attrCount = parser->getAttributeCount(); 20375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (attrCount > 0) { 20475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->attributes.reserve(attrCount); 20575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski for (size_t i = 0; i < attrCount; i++) { 20675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Attribute attr; 20775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski size_t len; 20875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski const char16_t* str16 = parser->getAttributeNamespace(i, &len); 20975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 21075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski attr.namespaceUri.assign(str16, len); 21175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 21275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 21375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski str16 = parser->getAttributeName(i, &len); 21475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 21575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski attr.name.assign(str16, len); 21675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 21775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 21875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski str16 = parser->getAttributeStringValue(i, &len); 21975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 22075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski attr.value.assign(str16, len); 22175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 22275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->attributes.push_back(std::move(attr)); 22375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 22475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 22575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 22675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 22775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistd::unique_ptr<Node> inflate(const void* data, size_t dataLen, SourceLogger* logger) { 22875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Node> root; 22975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::stack<Node*> nodeStack; 23075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 23175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski android::ResXMLTree tree; 23275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (tree.setTo(data, dataLen) != android::NO_ERROR) { 23375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return {}; 23475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 23575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 23675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski android::ResXMLParser::event_code_t code; 23775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski while ((code = tree.next()) != android::ResXMLParser::BAD_DOCUMENT && 23875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski code != android::ResXMLParser::END_DOCUMENT) { 23975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Node> newNode; 24075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski switch (code) { 24175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski case android::ResXMLParser::START_NAMESPACE: { 24275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Namespace> node = util::make_unique<Namespace>(); 24375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski size_t len; 24475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski const char16_t* str16 = tree.getNamespacePrefix(&len); 24575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 24675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski node->namespacePrefix.assign(str16, len); 24775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 24875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 24975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski str16 = tree.getNamespaceUri(&len); 25075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 25175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski node->namespaceUri.assign(str16, len); 25275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 25375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski newNode = std::move(node); 25475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 25575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 25675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 25775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski case android::ResXMLParser::START_TAG: { 25875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Element> node = util::make_unique<Element>(); 25975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski size_t len; 26075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski const char16_t* str16 = tree.getElementNamespace(&len); 26175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 26275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski node->namespaceUri.assign(str16, len); 26375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 26475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 26575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski str16 = tree.getElementName(&len); 26675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 26775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski node->name.assign(str16, len); 26875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 26975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 27075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski copyAttributes(node.get(), &tree); 27175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 27275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski newNode = std::move(node); 27375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 27475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 27575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 27675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski case android::ResXMLParser::TEXT: { 27775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Text> node = util::make_unique<Text>(); 27875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski size_t len; 27975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski const char16_t* str16 = tree.getText(&len); 28075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 28175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski node->text.assign(str16, len); 28275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 28375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski newNode = std::move(node); 28475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 28575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 28675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 28775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski case android::ResXMLParser::END_NAMESPACE: 28875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski case android::ResXMLParser::END_TAG: 28975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski assert(!nodeStack.empty()); 29075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski nodeStack.pop(); 29175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 29275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 29375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski default: 29475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski assert(false); 29575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 29675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 29775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 29875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (newNode) { 29975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski newNode->lineNumber = tree.getLineNumber(); 30075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 30175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Node* thisNode = newNode.get(); 30275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (!root) { 30375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski assert(nodeStack.empty()); 30475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski root = std::move(newNode); 30575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } else { 30675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski assert(!nodeStack.empty()); 30775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski nodeStack.top()->addChild(std::move(newNode)); 30875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 30975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 31075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (thisNode->type != NodeType::kText) { 31175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski nodeStack.push(thisNode); 31275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 31375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 31475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 31575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return std::move(root); 31675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 31775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 31875f3a55cc569a9b61f540a85d9828e91bdca5047Adam LesinskiNode::Node(NodeType type) : type(type), parent(nullptr), lineNumber(0), columnNumber(0) { 31975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 32075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 32175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskivoid Node::addChild(std::unique_ptr<Node> child) { 32275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski child->parent = this; 32375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski children.push_back(std::move(child)); 32475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 32575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 32675f3a55cc569a9b61f540a85d9828e91bdca5047Adam LesinskiNamespace::Namespace() : BaseNode(NodeType::kNamespace) { 32775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 32875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 32975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistd::unique_ptr<Node> Namespace::clone() const { 33075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Namespace* ns = new Namespace(); 33175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski ns->lineNumber = lineNumber; 33275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski ns->columnNumber = columnNumber; 33375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski ns->comment = comment; 33475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski ns->namespacePrefix = namespacePrefix; 33575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski ns->namespaceUri = namespaceUri; 33675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski for (auto& child : children) { 33775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski ns->addChild(child->clone()); 33875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 33975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return std::unique_ptr<Node>(ns); 34075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 34175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 34275f3a55cc569a9b61f540a85d9828e91bdca5047Adam LesinskiElement::Element() : BaseNode(NodeType::kElement) { 34375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 34475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 34575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistd::unique_ptr<Node> Element::clone() const { 34675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Element* el = new Element(); 34775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->lineNumber = lineNumber; 34875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->columnNumber = columnNumber; 34975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->comment = comment; 35075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->namespaceUri = namespaceUri; 35175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->name = name; 35275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->attributes = attributes; 35375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski for (auto& child : children) { 35475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->addChild(child->clone()); 35575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 35675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return std::unique_ptr<Node>(el); 35775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 35875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 35975f3a55cc569a9b61f540a85d9828e91bdca5047Adam LesinskiAttribute* Element::findAttribute(const StringPiece16& ns, const StringPiece16& name) { 36075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski for (auto& attr : attributes) { 36175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (ns == attr.namespaceUri && name == attr.name) { 36275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return &attr; 36375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 36475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 36575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return nullptr; 36675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 36775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 36875f3a55cc569a9b61f540a85d9828e91bdca5047Adam LesinskiElement* Element::findChild(const StringPiece16& ns, const StringPiece16& name) { 36975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return findChildWithAttribute(ns, name, nullptr); 37075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 37175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 37275f3a55cc569a9b61f540a85d9828e91bdca5047Adam LesinskiElement* Element::findChildWithAttribute(const StringPiece16& ns, const StringPiece16& name, 37375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski const Attribute* reqAttr) { 37475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski for (auto& childNode : children) { 37575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Node* child = childNode.get(); 37675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski while (child->type == NodeType::kNamespace) { 37775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (child->children.empty()) { 37875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 37975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 38075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski child = child->children[0].get(); 38175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 38275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 38375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (child->type == NodeType::kElement) { 38475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Element* el = static_cast<Element*>(child); 38575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (ns == el->namespaceUri && name == el->name) { 38675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (!reqAttr) { 38775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return el; 38875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 38975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 39075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Attribute* attrName = el->findAttribute(reqAttr->namespaceUri, reqAttr->name); 39175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (attrName && attrName->value == reqAttr->value) { 39275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return el; 39375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 39475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 39575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 39675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 39775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return nullptr; 39875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 39975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 40075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistd::vector<Element*> Element::getChildElements() { 40175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::vector<Element*> elements; 40275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski for (auto& childNode : children) { 40375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Node* child = childNode.get(); 40475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski while (child->type == NodeType::kNamespace) { 40575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (child->children.empty()) { 40675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 40775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 40875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski child = child->children[0].get(); 40975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 41075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 41175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (child->type == NodeType::kElement) { 41275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski elements.push_back(static_cast<Element*>(child)); 41375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 41475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 41575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return elements; 41675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 41775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 41875f3a55cc569a9b61f540a85d9828e91bdca5047Adam LesinskiText::Text() : BaseNode(NodeType::kText) { 41975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 42075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 42175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistd::unique_ptr<Node> Text::clone() const { 42275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Text* el = new Text(); 42375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->lineNumber = lineNumber; 42475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->columnNumber = columnNumber; 42575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->comment = comment; 42675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->text = text; 42775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return std::unique_ptr<Node>(el); 42875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 42975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 43075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} // namespace xml 43175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} // namespace aapt 432