blob: 7d50935eabfd0a97cd4637e2db3a85e0b5412b42 [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
Alexandria Cornwall77788eb2016-09-06 15:16:49 -070020#include <map>
21#include <memory>
22#include <string>
23#include <vector>
24
Adam Lesinskice5e56e2016-10-21 17:56:45 -070025#include "ResourceTable.h"
26
Alexandria Cornwall77788eb2016-09-06 15:16:49 -070027namespace 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 {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070049 public:
50 explicit DominatorTree(
51 const std::vector<std::unique_ptr<ResourceConfigValue>>& configs);
Alexandria Cornwall77788eb2016-09-06 15:16:49 -070052
Adam Lesinskicacb28f2016-10-19 12:18:14 -070053 class Node {
54 public:
55 explicit Node(ResourceConfigValue* value = nullptr, Node* parent = nullptr)
Adam Lesinskice5e56e2016-10-21 17:56:45 -070056 : value_(value), parent_(parent) {}
Alexandria Cornwall77788eb2016-09-06 15:16:49 -070057
Adam Lesinskice5e56e2016-10-21 17:56:45 -070058 inline ResourceConfigValue* value() const { return value_; }
Alexandria Cornwall77788eb2016-09-06 15:16:49 -070059
Adam Lesinskice5e56e2016-10-21 17:56:45 -070060 inline Node* parent() const { return parent_; }
Alexandria Cornwall77788eb2016-09-06 15:16:49 -070061
Adam Lesinskice5e56e2016-10-21 17:56:45 -070062 inline bool is_root_node() const { return !value_; }
Alexandria Cornwall77788eb2016-09-06 15:16:49 -070063
Adam Lesinskicacb28f2016-10-19 12:18:14 -070064 inline const std::vector<std::unique_ptr<Node>>& children() const {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070065 return children_;
Alexandria Cornwall77788eb2016-09-06 15:16:49 -070066 }
67
Adam Lesinskice5e56e2016-10-21 17:56:45 -070068 bool TryAddChild(std::unique_ptr<Node> new_child);
Alexandria Cornwall77788eb2016-09-06 15:16:49 -070069
Adam Lesinskicacb28f2016-10-19 12:18:14 -070070 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -070071 bool AddChild(std::unique_ptr<Node> new_child);
72 bool Dominates(const Node* other) const;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070073
Adam Lesinskice5e56e2016-10-21 17:56:45 -070074 ResourceConfigValue* value_;
75 Node* parent_;
76 std::vector<std::unique_ptr<Node>> children_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070077
78 DISALLOW_COPY_AND_ASSIGN(Node);
79 };
80
81 struct Visitor {
82 virtual ~Visitor() = default;
Adam Lesinskice5e56e2016-10-21 17:56:45 -070083 virtual void VisitTree(const std::string& product, Node* root) = 0;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070084 };
85
86 class BottomUpVisitor : public Visitor {
87 public:
88 virtual ~BottomUpVisitor() = default;
89
Adam Lesinskice5e56e2016-10-21 17:56:45 -070090 void VisitTree(const std::string& product, Node* root) override {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070091 for (auto& child : root->children()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070092 VisitNode(child.get());
Adam Lesinskicacb28f2016-10-19 12:18:14 -070093 }
94 }
95
Adam Lesinskice5e56e2016-10-21 17:56:45 -070096 virtual void VisitConfig(Node* node) = 0;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070097
98 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -070099 void VisitNode(Node* node) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700100 for (auto& child : node->children()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700101 VisitNode(child.get());
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700102 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700103 VisitConfig(node);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700104 }
105 };
106
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700107 void Accept(Visitor* visitor);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700108
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700109 inline const std::map<std::string, Node>& product_roots() const {
110 return product_roots_;
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700111 }
112
113 private:
114 DISALLOW_COPY_AND_ASSIGN(DominatorTree);
115
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700116 std::map<std::string, Node> product_roots_;
Alexandria Cornwall77788eb2016-09-06 15:16:49 -0700117};
118
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700119} // namespace aapt
Alexandria Cornwall77788eb2016-09-06 15:16:49 -0700120
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700121#endif // AAPT_DOMINATOR_TREE_H