XmlDom.cpp revision ca5638fd85098c3d0a699492751043545f75553a
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 171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "util/Util.h" 1875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include "XmlDom.h" 1975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include "XmlPullParser.h" 2075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 2175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <cassert> 2275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <memory> 2375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <stack> 2475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <string> 2575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski#include <tuple> 2675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 2775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace aapt { 2875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskinamespace xml { 2975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 3075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskiconstexpr char kXmlNamespaceSep = 1; 3175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 3275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistruct Stack { 3375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<xml::Node> root; 3475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::stack<xml::Node*> nodeStack; 3575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::u16string pendingComment; 3675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski}; 3775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 3875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski/** 3975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski * Extracts the namespace and name of an expanded element or attribute name. 4075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski */ 4175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void splitName(const char* name, std::u16string* outNs, std::u16string* outName) { 4275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski const char* p = name; 4375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski while (*p != 0 && *p != kXmlNamespaceSep) { 4475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski p++; 4575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 4675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 4775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (*p == 0) { 4875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski outNs->clear(); 4975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski *outName = util::utf8ToUtf16(name); 5075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } else { 5175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski *outNs = util::utf8ToUtf16(StringPiece(name, (p - name))); 5275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski *outName = util::utf8ToUtf16(p + 1); 5375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 5475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 5575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 5675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void addToStack(Stack* stack, XML_Parser parser, std::unique_ptr<Node> node) { 5775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski node->lineNumber = XML_GetCurrentLineNumber(parser); 5875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski node->columnNumber = XML_GetCurrentColumnNumber(parser); 5975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 6075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Node* thisNode = node.get(); 6175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (!stack->nodeStack.empty()) { 6275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack->nodeStack.top()->addChild(std::move(node)); 6375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } else { 6475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack->root = std::move(node); 6575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 6675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (!nodeCast<Text>(thisNode)) { 6875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack->nodeStack.push(thisNode); 6975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 7075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 7175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 7275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void XMLCALL startNamespaceHandler(void* userData, const char* prefix, const char* uri) { 7375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(userData); 7475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 7575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 7675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Namespace> ns = util::make_unique<Namespace>(); 7775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (prefix) { 7875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski ns->namespacePrefix = util::utf8ToUtf16(prefix); 7975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 8075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 8175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (uri) { 8275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski ns->namespaceUri = util::utf8ToUtf16(uri); 8375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 8475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 8575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski addToStack(stack, parser, std::move(ns)); 8675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 8775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 8875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void XMLCALL endNamespaceHandler(void* userData, const char* prefix) { 8975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(userData); 9075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 9175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 9275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski assert(!stack->nodeStack.empty()); 9375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack->nodeStack.pop(); 9475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 9575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 9675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic bool lessAttribute(const Attribute& lhs, const Attribute& rhs) { 9775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return std::tie(lhs.namespaceUri, lhs.name, lhs.value) < 9875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::tie(rhs.namespaceUri, rhs.name, rhs.value); 9975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 10075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 10175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void XMLCALL startElementHandler(void* userData, const char* name, const char** attrs) { 10275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(userData); 10375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 10475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 10575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Element> el = util::make_unique<Element>(); 10675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski splitName(name, &el->namespaceUri, &el->name); 10775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 10875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski while (*attrs) { 10975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Attribute attribute; 11075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski splitName(*attrs++, &attribute.namespaceUri, &attribute.name); 11175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski attribute.value = util::utf8ToUtf16(*attrs++); 11275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 11375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski // Insert in sorted order. 11475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski auto iter = std::lower_bound(el->attributes.begin(), el->attributes.end(), attribute, 11575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski lessAttribute); 11675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->attributes.insert(iter, std::move(attribute)); 11775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 11875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 11975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->comment = std::move(stack->pendingComment); 12075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski addToStack(stack, parser, std::move(el)); 12175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 12275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 12375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void XMLCALL endElementHandler(void* userData, const char* name) { 12475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(userData); 12575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 12675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 12775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski assert(!stack->nodeStack.empty()); 128ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski //stack->nodeStack.top()->comment = std::move(stack->pendingComment); 12975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack->nodeStack.pop(); 13075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 13175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 13275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void XMLCALL characterDataHandler(void* userData, const char* s, int len) { 13375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(userData); 13475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 13575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 13675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (!s || len <= 0) { 13775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return; 13875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 13975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 14075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski // See if we can just append the text to a previous text node. 14175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (!stack->nodeStack.empty()) { 14275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Node* currentParent = stack->nodeStack.top(); 14375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (!currentParent->children.empty()) { 14475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Node* lastChild = currentParent->children.back().get(); 1451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (Text* text = nodeCast<Text>(lastChild)) { 14675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski text->text += util::utf8ToUtf16(StringPiece(s, len)); 14775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return; 14875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 14975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 15075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 15175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 15275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Text> text = util::make_unique<Text>(); 15375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski text->text = util::utf8ToUtf16(StringPiece(s, len)); 15475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski addToStack(stack, parser, std::move(text)); 15575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 15675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 15775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void XMLCALL commentDataHandler(void* userData, const char* comment) { 15875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_Parser parser = reinterpret_cast<XML_Parser>(userData); 15975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser)); 16075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 16175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (!stack->pendingComment.empty()) { 16275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack->pendingComment += '\n'; 16375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 16475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack->pendingComment += util::utf8ToUtf16(comment); 16575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 16675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 1671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistd::unique_ptr<XmlResource> inflate(std::istream* in, IDiagnostics* diag, const Source& source) { 16875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Stack stack; 16975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 17075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_Parser parser = XML_ParserCreateNS(nullptr, kXmlNamespaceSep); 17175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_SetUserData(parser, &stack); 17275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_UseParserAsHandlerArg(parser); 17375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_SetElementHandler(parser, startElementHandler, endElementHandler); 17475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_SetNamespaceDeclHandler(parser, startNamespaceHandler, endNamespaceHandler); 17575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_SetCharacterDataHandler(parser, characterDataHandler); 17675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_SetCommentHandler(parser, commentDataHandler); 17775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 17875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski char buffer[1024]; 17975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski while (!in->eof()) { 18075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski in->read(buffer, sizeof(buffer) / sizeof(buffer[0])); 18175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (in->bad() && !in->eof()) { 18275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack.root = {}; 1831ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski diag->error(DiagMessage(source) << strerror(errno)); 18475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 18575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 18675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 18775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (XML_Parse(parser, buffer, in->gcount(), in->eof()) == XML_STATUS_ERROR) { 18875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski stack.root = {}; 1891ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski diag->error(DiagMessage(source.withLine(XML_GetCurrentLineNumber(parser))) 1901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski << XML_ErrorString(XML_GetErrorCode(parser))); 19175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 19275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 19375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 19475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 19575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski XML_ParserFree(parser); 1961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (stack.root) { 197ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski return util::make_unique<XmlResource>(ResourceFile{ {}, {}, source }, std::move(stack.root)); 1981ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski } 1991ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return {}; 20075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 20175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 20275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistatic void copyAttributes(Element* el, android::ResXMLParser* parser) { 20375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski const size_t attrCount = parser->getAttributeCount(); 20475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (attrCount > 0) { 20575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->attributes.reserve(attrCount); 20675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski for (size_t i = 0; i < attrCount; i++) { 20775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Attribute attr; 20875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski size_t len; 20975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski const char16_t* str16 = parser->getAttributeNamespace(i, &len); 21075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 21175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski attr.namespaceUri.assign(str16, len); 21275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 21375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 21475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski str16 = parser->getAttributeName(i, &len); 21575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 21675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski attr.name.assign(str16, len); 21775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 21875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 21975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski str16 = parser->getAttributeStringValue(i, &len); 22075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 22175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski attr.value.assign(str16, len); 22275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 22375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski el->attributes.push_back(std::move(attr)); 22475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 22575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 22675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 22775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 2281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistd::unique_ptr<XmlResource> inflate(const void* data, size_t dataLen, IDiagnostics* diag, 2291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski const Source& source) { 23075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Node> root; 23175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::stack<Node*> nodeStack; 23275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 23375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski android::ResXMLTree tree; 23475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (tree.setTo(data, dataLen) != android::NO_ERROR) { 23575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return {}; 23675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 23775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 23875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski android::ResXMLParser::event_code_t code; 23975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski while ((code = tree.next()) != android::ResXMLParser::BAD_DOCUMENT && 24075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski code != android::ResXMLParser::END_DOCUMENT) { 24175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Node> newNode; 24275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski switch (code) { 24375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski case android::ResXMLParser::START_NAMESPACE: { 24475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Namespace> node = util::make_unique<Namespace>(); 24575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski size_t len; 24675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski const char16_t* str16 = tree.getNamespacePrefix(&len); 24775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 24875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski node->namespacePrefix.assign(str16, len); 24975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 25075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 25175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski str16 = tree.getNamespaceUri(&len); 25275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 25375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski node->namespaceUri.assign(str16, len); 25475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 25575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski newNode = std::move(node); 25675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 25775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 25875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 25975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski case android::ResXMLParser::START_TAG: { 26075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Element> node = util::make_unique<Element>(); 26175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski size_t len; 26275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski const char16_t* str16 = tree.getElementNamespace(&len); 26375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 26475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski node->namespaceUri.assign(str16, len); 26575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 26675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 26775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski str16 = tree.getElementName(&len); 26875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 26975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski node->name.assign(str16, len); 27075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 27175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 27275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski copyAttributes(node.get(), &tree); 27375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 27475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski newNode = std::move(node); 27575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 27675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 27775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 27875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski case android::ResXMLParser::TEXT: { 27975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::unique_ptr<Text> node = util::make_unique<Text>(); 28075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski size_t len; 28175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski const char16_t* str16 = tree.getText(&len); 28275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (str16) { 28375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski node->text.assign(str16, len); 28475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 28575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski newNode = std::move(node); 28675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 28775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 28875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 28975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski case android::ResXMLParser::END_NAMESPACE: 29075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski case android::ResXMLParser::END_TAG: 29175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski assert(!nodeStack.empty()); 29275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski nodeStack.pop(); 29375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 29475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 29575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski default: 29675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski assert(false); 29775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 29875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 29975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 30075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (newNode) { 30175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski newNode->lineNumber = tree.getLineNumber(); 30275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 30375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Node* thisNode = newNode.get(); 30475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (!root) { 30575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski assert(nodeStack.empty()); 30675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski root = std::move(newNode); 30775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } else { 30875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski assert(!nodeStack.empty()); 30975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski nodeStack.top()->addChild(std::move(newNode)); 31075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 31175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 3121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (!nodeCast<Text>(thisNode)) { 31375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski nodeStack.push(thisNode); 31475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 31575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 31675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 3171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return util::make_unique<XmlResource>(ResourceFile{}, std::move(root)); 31875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 31975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 320ca5638fd85098c3d0a699492751043545f75553aAdam LesinskiElement* findRootElement(Node* node) { 321ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski if (!node) { 322ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski return nullptr; 323ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 324ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 325ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski Element* el = nullptr; 326ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski while ((el = nodeCast<Element>(node)) == nullptr) { 327ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski if (node->children.empty()) { 328ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski return nullptr; 329ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 330ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski // We are looking for the first element, and namespaces can only have one child. 331ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski node = node->children.front().get(); 332ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski } 333ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski return el; 334ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski} 335ca5638fd85098c3d0a699492751043545f75553aAdam Lesinski 33675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskivoid Node::addChild(std::unique_ptr<Node> child) { 33775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski child->parent = this; 33875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski children.push_back(std::move(child)); 33975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 34075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 34175f3a55cc569a9b61f540a85d9828e91bdca5047Adam LesinskiAttribute* Element::findAttribute(const StringPiece16& ns, const StringPiece16& name) { 34275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski for (auto& attr : attributes) { 34375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (ns == attr.namespaceUri && name == attr.name) { 34475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return &attr; 34575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 34675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 34775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return nullptr; 34875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 34975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 35075f3a55cc569a9b61f540a85d9828e91bdca5047Adam LesinskiElement* Element::findChild(const StringPiece16& ns, const StringPiece16& name) { 3511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski return findChildWithAttribute(ns, name, {}, {}, {}); 35275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 35375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 35475f3a55cc569a9b61f540a85d9828e91bdca5047Adam LesinskiElement* Element::findChildWithAttribute(const StringPiece16& ns, const StringPiece16& name, 3551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski const StringPiece16& attrNs, const StringPiece16& attrName, 3561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski const StringPiece16& attrValue) { 35775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski for (auto& childNode : children) { 35875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Node* child = childNode.get(); 3591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski while (nodeCast<Namespace>(child)) { 36075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (child->children.empty()) { 36175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 36275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 36375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski child = child->children[0].get(); 36475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 36575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 3661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (Element* el = nodeCast<Element>(child)) { 36775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (ns == el->namespaceUri && name == el->name) { 3681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (attrNs.empty() && attrName.empty()) { 36975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return el; 37075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 37175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 3721ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski Attribute* attr = el->findAttribute(attrNs, attrName); 3731ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (attr && attrValue == attr->value) { 37475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return el; 37575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 37675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 37775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 37875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 37975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return nullptr; 38075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 38175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 38275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinskistd::vector<Element*> Element::getChildElements() { 38375f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski std::vector<Element*> elements; 38475f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski for (auto& childNode : children) { 38575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski Node* child = childNode.get(); 3861ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski while (nodeCast<Namespace>(child)) { 38775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski if (child->children.empty()) { 38875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski break; 38975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 39075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski child = child->children[0].get(); 39175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 39275f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 3931ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski if (Element* el = nodeCast<Element>(child)) { 3941ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski elements.push_back(el); 39575f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 39675f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski } 39775f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski return elements; 39875f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} 39975f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski 40075f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} // namespace xml 40175f3a55cc569a9b61f540a85d9828e91bdca5047Adam Lesinski} // namespace aapt 402