blob: e4f41b03dbe02c5e3edb2c43cc46d5d3990bcdd4 [file] [log] [blame]
Adam Lesinski75f3a552015-06-03 14:54:23 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef AAPT_XML_DOM_H
18#define AAPT_XML_DOM_H
19
Adam Lesinski1ab598f2015-08-14 14:26:04 -070020#include "Diagnostics.h"
21#include "Resource.h"
22#include "ResourceValues.h"
23#include "util/StringPiece.h"
24#include "util/Util.h"
Adam Lesinski467f1712015-11-16 17:35:44 -080025#include "xml/XmlUtil.h"
Adam Lesinski75f3a552015-06-03 14:54:23 -070026
27#include <istream>
Adam Lesinski75f3a552015-06-03 14:54:23 -070028#include <memory>
29#include <string>
30#include <vector>
31
32namespace aapt {
33namespace xml {
34
Adam Lesinski5eeaadd2016-08-25 12:26:56 -070035class RawVisitor;
Adam Lesinski75f3a552015-06-03 14:54:23 -070036
37/**
Adam Lesinski75f3a552015-06-03 14:54:23 -070038 * Base class for all XML nodes.
39 */
Adam Lesinski5eeaadd2016-08-25 12:26:56 -070040class Node {
41public:
Adam Lesinski1ab598f2015-08-14 14:26:04 -070042 Node* parent = nullptr;
43 size_t lineNumber = 0;
44 size_t columnNumber = 0;
Adam Lesinskid0f116b2016-07-08 15:00:32 -070045 std::string comment;
Adam Lesinski75f3a552015-06-03 14:54:23 -070046 std::vector<std::unique_ptr<Node>> children;
47
Adam Lesinski467f1712015-11-16 17:35:44 -080048 virtual ~Node() = default;
49
Adam Lesinski75f3a552015-06-03 14:54:23 -070050 void addChild(std::unique_ptr<Node> child);
Adam Lesinski1ab598f2015-08-14 14:26:04 -070051 virtual void accept(RawVisitor* visitor) = 0;
Adam Lesinski5eeaadd2016-08-25 12:26:56 -070052 virtual std::unique_ptr<Node> clone() = 0;
Adam Lesinski75f3a552015-06-03 14:54:23 -070053};
54
55/**
56 * Base class that implements the visitor methods for a
57 * subclass of Node.
58 */
59template <typename Derived>
Adam Lesinski5eeaadd2016-08-25 12:26:56 -070060class BaseNode : public Node {
61public:
Adam Lesinski1ab598f2015-08-14 14:26:04 -070062 virtual void accept(RawVisitor* visitor) override;
Adam Lesinski75f3a552015-06-03 14:54:23 -070063};
64
65/**
66 * A Namespace XML node. Can only have one child.
67 */
Adam Lesinski5eeaadd2016-08-25 12:26:56 -070068class Namespace : public BaseNode<Namespace> {
69public:
Adam Lesinskid0f116b2016-07-08 15:00:32 -070070 std::string namespacePrefix;
71 std::string namespaceUri;
Adam Lesinski5eeaadd2016-08-25 12:26:56 -070072
73 std::unique_ptr<Node> clone() override;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070074};
Adam Lesinski75f3a552015-06-03 14:54:23 -070075
Adam Lesinski1ab598f2015-08-14 14:26:04 -070076struct AaptAttribute {
Adam Lesinski64587af2016-02-18 18:33:06 -080077 Maybe<ResourceId> id;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070078 aapt::Attribute attribute;
Adam Lesinski75f3a552015-06-03 14:54:23 -070079};
80
81/**
82 * An XML attribute.
83 */
84struct Attribute {
Adam Lesinskid0f116b2016-07-08 15:00:32 -070085 std::string namespaceUri;
86 std::string name;
87 std::string value;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070088
89 Maybe<AaptAttribute> compiledAttribute;
90 std::unique_ptr<Item> compiledValue;
Adam Lesinski75f3a552015-06-03 14:54:23 -070091};
92
93/**
94 * An Element XML node.
95 */
Adam Lesinski5eeaadd2016-08-25 12:26:56 -070096class Element : public BaseNode<Element> {
97public:
Adam Lesinskid0f116b2016-07-08 15:00:32 -070098 std::string namespaceUri;
99 std::string name;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700100 std::vector<Attribute> attributes;
101
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700102 Attribute* findAttribute(const StringPiece& ns, const StringPiece& name);
103 xml::Element* findChild(const StringPiece& ns, const StringPiece& name);
104 xml::Element* findChildWithAttribute(const StringPiece& ns, const StringPiece& name,
105 const StringPiece& attrNs,
106 const StringPiece& attrName,
107 const StringPiece& attrValue);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700108 std::vector<xml::Element*> getChildElements();
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700109 std::unique_ptr<Node> clone() override;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700110};
111
112/**
113 * A Text (CDATA) XML node. Can not have any children.
114 */
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700115class Text : public BaseNode<Text> {
116public:
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700117 std::string text;
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700118
119 std::unique_ptr<Node> clone() override;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700120};
121
122/**
Adam Lesinski467f1712015-11-16 17:35:44 -0800123 * An XML resource with a source, name, and XML tree.
124 */
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700125class XmlResource {
126public:
Adam Lesinski467f1712015-11-16 17:35:44 -0800127 ResourceFile file;
128 std::unique_ptr<xml::Node> root;
129};
130
131/**
Adam Lesinski75f3a552015-06-03 14:54:23 -0700132 * Inflates an XML DOM from a text stream, logging errors to the logger.
133 * Returns the root node on success, or nullptr on failure.
134 */
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700135std::unique_ptr<XmlResource> inflate(std::istream* in, IDiagnostics* diag, const Source& source);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700136
137/**
138 * Inflates an XML DOM from a binary ResXMLTree, logging errors to the logger.
139 * Returns the root node on success, or nullptr on failure.
140 */
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700141std::unique_ptr<XmlResource> inflate(const void* data, size_t dataLen, IDiagnostics* diag,
142 const Source& source);
Adam Lesinski75f3a552015-06-03 14:54:23 -0700143
Adam Lesinski467f1712015-11-16 17:35:44 -0800144Element* findRootElement(XmlResource* doc);
Adam Lesinskica5638f2015-10-21 14:42:43 -0700145Element* findRootElement(Node* node);
146
Adam Lesinski75f3a552015-06-03 14:54:23 -0700147/**
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700148 * A visitor interface for the different XML Node subtypes. This will not traverse into
149 * children. Use Visitor for that.
Adam Lesinski75f3a552015-06-03 14:54:23 -0700150 */
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700151class RawVisitor {
152public:
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700153 virtual ~RawVisitor() = default;
154
155 virtual void visit(Namespace* node) {}
156 virtual void visit(Element* node) {}
157 virtual void visit(Text* text) {}
158};
159
160/**
161 * Visitor whose default implementation visits the children nodes of any node.
162 */
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700163class Visitor : public RawVisitor {
164public:
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700165 using RawVisitor::visit;
166
167 void visit(Namespace* node) override {
168 visitChildren(node);
169 }
170
171 void visit(Element* node) override {
172 visitChildren(node);
173 }
174
175 void visit(Text* text) override {
176 visitChildren(text);
177 }
178
179 void visitChildren(Node* node) {
180 for (auto& child : node->children) {
181 child->accept(this);
182 }
183 }
184};
185
186/**
187 * An XML DOM visitor that will record the package name for a namespace prefix.
188 */
189class PackageAwareVisitor : public Visitor, public IPackageDeclStack {
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700190public:
191 using Visitor::visit;
192
193 void visit(Namespace* ns) override;
194 Maybe<ExtractedPackage> transformPackageAlias(
195 const StringPiece& alias, const StringPiece& localPackage) const override;
196
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700197private:
198 struct PackageDecl {
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700199 std::string prefix;
Adam Lesinski467f1712015-11-16 17:35:44 -0800200 ExtractedPackage package;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700201 };
202
203 std::vector<PackageDecl> mPackageDecls;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700204};
205
206// Implementations
207
208template <typename Derived>
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700209void BaseNode<Derived>::accept(RawVisitor* visitor) {
210 visitor->visit(static_cast<Derived*>(this));
Adam Lesinski75f3a552015-06-03 14:54:23 -0700211}
212
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700213template <typename T>
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700214class NodeCastImpl : public RawVisitor {
215public:
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700216 using RawVisitor::visit;
217
218 T* value = nullptr;
219
220 void visit(T* v) override {
221 value = v;
222 }
223};
224
225template <typename T>
226T* nodeCast(Node* node) {
227 NodeCastImpl<T> visitor;
228 node->accept(&visitor);
229 return visitor.value;
Adam Lesinski75f3a552015-06-03 14:54:23 -0700230}
231
232} // namespace xml
233} // namespace aapt
234
235#endif // AAPT_XML_DOM_H