blob: ad2df0e4fd66bcf49cee9701c320a136b748f472 [file] [log] [blame]
Alexandria Cornwall77788eb2016-09-06 15:16:49 -07001/*
2 * Copyright (C) 2016 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_DOMINATOR_TREE_H
18#define AAPT_DOMINATOR_TREE_H
19
20#include "ResourceTable.h"
21
22#include <map>
23#include <memory>
24#include <string>
25#include <vector>
26
27namespace aapt {
28
29/**
30 * A dominator tree of configurations as defined by resolution rules for Android
31 * resources.
32 *
33 * A node in the tree represents a resource configuration.
34 *
35 * The tree has the following property:
36 *
37 * Each child of a given configuration defines a strict superset of qualifiers
38 * and has a value that is at least as specific as that of its ancestors. A
39 * value is "at least as specific" if it is either identical or it represents a
40 * stronger requirement.
41 * For example, v21 is more specific than v11, and w1200dp is more specific than
42 * w800dp.
43 *
44 * The dominator tree relies on the underlying configurations passed to it. If
45 * the configurations passed to the dominator tree go out of scope, the tree
46 * will exhibit undefined behavior.
47 */
48class DominatorTree {
49public:
50 explicit DominatorTree(const std::vector<std::unique_ptr<ResourceConfigValue>>& configs);
51
52 class Node {
53 public:
54 explicit Node(ResourceConfigValue* value = nullptr, Node* parent = nullptr) :
55 mValue(value), mParent(parent) {
56 }
57
58 inline ResourceConfigValue* value() const {
59 return mValue;
60 }
61
62 inline Node* parent() const {
63 return mParent;
64 }
65
66 inline bool isRootNode() const {
67 return !mValue;
68 }
69
70 inline const std::vector<std::unique_ptr<Node>>& children() const {
71 return mChildren;
72 }
73
74 bool tryAddChild(std::unique_ptr<Node> newChild);
75
76 private:
77 bool addChild(std::unique_ptr<Node> newChild);
78 bool dominates(const Node* other) const;
79
80 ResourceConfigValue* mValue;
81 Node* mParent;
82 std::vector<std::unique_ptr<Node>> mChildren;
83
84 DISALLOW_COPY_AND_ASSIGN(Node);
85 };
86
87 struct Visitor {
88 virtual ~Visitor() = default;
89 virtual void visitTree(const std::string& product, Node* root) = 0;
90 };
91
92 class BottomUpVisitor : public Visitor {
93 public:
94 virtual ~BottomUpVisitor() = default;
95
96 void visitTree(const std::string& product, Node* root) override {
97 for (auto& child : root->children()) {
98 visitNode(child.get());
99 }
100 }
101
102 virtual void visitConfig(Node* node) = 0;
103
104 private:
105 void visitNode(Node* node) {
106 for (auto& child : node->children()) {
107 visitNode(child.get());
108 }
109 visitConfig(node);
110 }
111 };
112
113 void accept(Visitor* visitor);
114
115 inline const std::map<std::string, Node>& getProductRoots() const {
116 return mProductRoots;
117 }
118
119private:
120 DISALLOW_COPY_AND_ASSIGN(DominatorTree);
121
122 std::map<std::string, Node> mProductRoots;
123};
124
125} // namespace aapt
126
127#endif // AAPT_DOMINATOR_TREE_H