• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
20 #include "Diagnostics.h"
21 #include "Resource.h"
22 #include "ResourceValues.h"
23 #include "util/StringPiece.h"
24 #include "util/Util.h"
25 #include "xml/XmlUtil.h"
26 
27 #include <istream>
28 #include <memory>
29 #include <string>
30 #include <vector>
31 
32 namespace aapt {
33 namespace xml {
34 
35 struct RawVisitor;
36 
37 /**
38  * Base class for all XML nodes.
39  */
40 struct Node {
41     Node* parent = nullptr;
42     size_t lineNumber = 0;
43     size_t columnNumber = 0;
44     std::u16string comment;
45     std::vector<std::unique_ptr<Node>> children;
46 
47     virtual ~Node() = default;
48 
49     void addChild(std::unique_ptr<Node> child);
50     virtual void accept(RawVisitor* visitor) = 0;
51 };
52 
53 /**
54  * Base class that implements the visitor methods for a
55  * subclass of Node.
56  */
57 template <typename Derived>
58 struct BaseNode : public Node {
59     virtual void accept(RawVisitor* visitor) override;
60 };
61 
62 /**
63  * A Namespace XML node. Can only have one child.
64  */
65 struct Namespace : public BaseNode<Namespace> {
66     std::u16string namespacePrefix;
67     std::u16string namespaceUri;
68 };
69 
70 struct AaptAttribute {
71     Maybe<ResourceId> id;
72     aapt::Attribute attribute;
73 };
74 
75 /**
76  * An XML attribute.
77  */
78 struct Attribute {
79     std::u16string namespaceUri;
80     std::u16string name;
81     std::u16string value;
82 
83     Maybe<AaptAttribute> compiledAttribute;
84     std::unique_ptr<Item> compiledValue;
85 };
86 
87 /**
88  * An Element XML node.
89  */
90 struct Element : public BaseNode<Element> {
91     std::u16string namespaceUri;
92     std::u16string name;
93     std::vector<Attribute> attributes;
94 
95     Attribute* findAttribute(const StringPiece16& ns, const StringPiece16& name);
96     xml::Element* findChild(const StringPiece16& ns, const StringPiece16& name);
97     xml::Element* findChildWithAttribute(const StringPiece16& ns, const StringPiece16& name,
98                                          const StringPiece16& attrNs,
99                                          const StringPiece16& attrName,
100                                          const StringPiece16& attrValue);
101     std::vector<xml::Element*> getChildElements();
102 };
103 
104 /**
105  * A Text (CDATA) XML node. Can not have any children.
106  */
107 struct Text : public BaseNode<Text> {
108     std::u16string text;
109 };
110 
111 /**
112  * An XML resource with a source, name, and XML tree.
113  */
114 struct XmlResource {
115     ResourceFile file;
116     std::unique_ptr<xml::Node> root;
117 };
118 
119 /**
120  * Inflates an XML DOM from a text stream, logging errors to the logger.
121  * Returns the root node on success, or nullptr on failure.
122  */
123 std::unique_ptr<XmlResource> inflate(std::istream* in, IDiagnostics* diag, const Source& source);
124 
125 /**
126  * Inflates an XML DOM from a binary ResXMLTree, logging errors to the logger.
127  * Returns the root node on success, or nullptr on failure.
128  */
129 std::unique_ptr<XmlResource> inflate(const void* data, size_t dataLen, IDiagnostics* diag,
130                                      const Source& source);
131 
132 Element* findRootElement(XmlResource* doc);
133 Element* findRootElement(Node* node);
134 
135 /**
136  * A visitor interface for the different XML Node subtypes. This will not traverse into
137  * children. Use Visitor for that.
138  */
139 struct RawVisitor {
140     virtual ~RawVisitor() = default;
141 
visitRawVisitor142     virtual void visit(Namespace* node) {}
visitRawVisitor143     virtual void visit(Element* node) {}
visitRawVisitor144     virtual void visit(Text* text) {}
145 };
146 
147 /**
148  * Visitor whose default implementation visits the children nodes of any node.
149  */
150 struct Visitor : public RawVisitor {
151     using RawVisitor::visit;
152 
visitVisitor153     void visit(Namespace* node) override {
154         visitChildren(node);
155     }
156 
visitVisitor157     void visit(Element* node) override {
158         visitChildren(node);
159     }
160 
visitVisitor161     void visit(Text* text) override {
162         visitChildren(text);
163     }
164 
visitChildrenVisitor165     void visitChildren(Node* node) {
166         for (auto& child : node->children) {
167             child->accept(this);
168         }
169     }
170 };
171 
172 /**
173  * An XML DOM visitor that will record the package name for a namespace prefix.
174  */
175 class PackageAwareVisitor : public Visitor, public IPackageDeclStack {
176 private:
177     struct PackageDecl {
178         std::u16string prefix;
179         ExtractedPackage package;
180     };
181 
182     std::vector<PackageDecl> mPackageDecls;
183 
184 public:
185     using Visitor::visit;
186 
187     void visit(Namespace* ns) override;
188     Maybe<ExtractedPackage> transformPackageAlias(
189             const StringPiece16& alias, const StringPiece16& localPackage) const override;
190 };
191 
192 // Implementations
193 
194 template <typename Derived>
accept(RawVisitor * visitor)195 void BaseNode<Derived>::accept(RawVisitor* visitor) {
196     visitor->visit(static_cast<Derived*>(this));
197 }
198 
199 template <typename T>
200 struct NodeCastImpl : public RawVisitor {
201     using RawVisitor::visit;
202 
203     T* value = nullptr;
204 
visitNodeCastImpl205     void visit(T* v) override {
206         value = v;
207     }
208 };
209 
210 template <typename T>
nodeCast(Node * node)211 T* nodeCast(Node* node) {
212     NodeCastImpl<T> visitor;
213     node->accept(&visitor);
214     return visitor.value;
215 }
216 
217 } // namespace xml
218 } // namespace aapt
219 
220 #endif // AAPT_XML_DOM_H
221