| /* | |
| * Copyright (C) 2016 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| #ifndef AAPT_DOMINATOR_TREE_H | |
| #define AAPT_DOMINATOR_TREE_H | |
| #include <map> | |
| #include <memory> | |
| #include <string> | |
| #include <vector> | |
| #include "ResourceTable.h" | |
| namespace aapt { | |
| /** | |
| * A dominator tree of configurations as defined by resolution rules for Android | |
| * resources. | |
| * | |
| * A node in the tree represents a resource configuration. | |
| * | |
| * The tree has the following property: | |
| * | |
| * Each child of a given configuration defines a strict superset of qualifiers | |
| * and has a value that is at least as specific as that of its ancestors. A | |
| * value is "at least as specific" if it is either identical or it represents a | |
| * stronger requirement. | |
| * For example, v21 is more specific than v11, and w1200dp is more specific than | |
| * w800dp. | |
| * | |
| * The dominator tree relies on the underlying configurations passed to it. If | |
| * the configurations passed to the dominator tree go out of scope, the tree | |
| * will exhibit undefined behavior. | |
| */ | |
| class DominatorTree { | |
| public: | |
| explicit DominatorTree( | |
| const std::vector<std::unique_ptr<ResourceConfigValue>>& configs); | |
| class Node { | |
| public: | |
| explicit Node(ResourceConfigValue* value = nullptr, Node* parent = nullptr) | |
| : value_(value), parent_(parent) {} | |
| inline ResourceConfigValue* value() const { return value_; } | |
| inline Node* parent() const { return parent_; } | |
| inline bool is_root_node() const { return !value_; } | |
| inline const std::vector<std::unique_ptr<Node>>& children() const { | |
| return children_; | |
| } | |
| bool TryAddChild(std::unique_ptr<Node> new_child); | |
| private: | |
| bool AddChild(std::unique_ptr<Node> new_child); | |
| bool Dominates(const Node* other) const; | |
| ResourceConfigValue* value_; | |
| Node* parent_; | |
| std::vector<std::unique_ptr<Node>> children_; | |
| DISALLOW_COPY_AND_ASSIGN(Node); | |
| }; | |
| struct Visitor { | |
| virtual ~Visitor() = default; | |
| virtual void VisitTree(const std::string& product, Node* root) = 0; | |
| }; | |
| class BottomUpVisitor : public Visitor { | |
| public: | |
| virtual ~BottomUpVisitor() = default; | |
| void VisitTree(const std::string& product, Node* root) override { | |
| for (auto& child : root->children()) { | |
| VisitNode(child.get()); | |
| } | |
| } | |
| virtual void VisitConfig(Node* node) = 0; | |
| private: | |
| void VisitNode(Node* node) { | |
| for (auto& child : node->children()) { | |
| VisitNode(child.get()); | |
| } | |
| VisitConfig(node); | |
| } | |
| }; | |
| void Accept(Visitor* visitor); | |
| inline const std::map<std::string, Node>& product_roots() const { | |
| return product_roots_; | |
| } | |
| private: | |
| DISALLOW_COPY_AND_ASSIGN(DominatorTree); | |
| std::map<std::string, Node> product_roots_; | |
| }; | |
| } // namespace aapt | |
| #endif // AAPT_DOMINATOR_TREE_H |