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 "Logger.h"
21#include "StringPiece.h"
22
23#include <istream>
24#include <libexpat/expat.h>
25#include <memory>
26#include <string>
27#include <vector>
28
29namespace aapt {
30namespace xml {
31
32struct Visitor;
33
34/**
35 * The type of node. Can be used to downcast to the concrete XML node
36 * class.
37 */
38enum class NodeType {
39    kNamespace,
40    kElement,
41    kText,
42};
43
44/**
45 * Base class for all XML nodes.
46 */
47struct Node {
48    NodeType type;
49    Node* parent;
50    size_t lineNumber;
51    size_t columnNumber;
52    std::u16string comment;
53    std::vector<std::unique_ptr<Node>> children;
54
55    Node(NodeType type);
56    void addChild(std::unique_ptr<Node> child);
57    virtual std::unique_ptr<Node> clone() const = 0;
58    virtual void accept(Visitor* visitor) = 0;
59    virtual ~Node() {}
60};
61
62/**
63 * Base class that implements the visitor methods for a
64 * subclass of Node.
65 */
66template <typename Derived>
67struct BaseNode : public Node {
68    BaseNode(NodeType t);
69    virtual void accept(Visitor* visitor) override;
70};
71
72/**
73 * A Namespace XML node. Can only have one child.
74 */
75struct Namespace : public BaseNode<Namespace> {
76    std::u16string namespacePrefix;
77    std::u16string namespaceUri;
78
79    Namespace();
80    virtual std::unique_ptr<Node> clone() const override;
81};
82
83/**
84 * An XML attribute.
85 */
86struct Attribute {
87    std::u16string namespaceUri;
88    std::u16string name;
89    std::u16string value;
90};
91
92/**
93 * An Element XML node.
94 */
95struct Element : public BaseNode<Element> {
96    std::u16string namespaceUri;
97    std::u16string name;
98    std::vector<Attribute> attributes;
99
100    Element();
101    virtual std::unique_ptr<Node> clone() const override;
102    Attribute* findAttribute(const StringPiece16& ns, const StringPiece16& name);
103    xml::Element* findChild(const StringPiece16& ns, const StringPiece16& name);
104    xml::Element* findChildWithAttribute(const StringPiece16& ns, const StringPiece16& name,
105                                         const xml::Attribute* reqAttr);
106    std::vector<xml::Element*> getChildElements();
107};
108
109/**
110 * A Text (CDATA) XML node. Can not have any children.
111 */
112struct Text : public BaseNode<Text> {
113    std::u16string text;
114
115    Text();
116    virtual std::unique_ptr<Node> clone() const override;
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 */
123std::unique_ptr<Node> inflate(std::istream* in, SourceLogger* logger);
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 */
129std::unique_ptr<Node> inflate(const void* data, size_t dataLen, SourceLogger* logger);
130
131/**
132 * A visitor interface for the different XML Node subtypes.
133 */
134struct Visitor {
135    virtual void visit(Namespace* node) = 0;
136    virtual void visit(Element* node) = 0;
137    virtual void visit(Text* text) = 0;
138};
139
140// Implementations
141
142template <typename Derived>
143BaseNode<Derived>::BaseNode(NodeType type) : Node(type) {
144}
145
146template <typename Derived>
147void BaseNode<Derived>::accept(Visitor* visitor) {
148    visitor->visit(static_cast<Derived*>(this));
149}
150
151} // namespace xml
152} // namespace aapt
153
154#endif // AAPT_XML_DOM_H
155