blob: d0c9d89b6f0cd0e2135c4e62e4979bb6a6a6e7fd [file] [log] [blame]
Adam Lesinski1ab598f2015-08-14 14:26:04 -07001/*
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_VALUE_VISITOR_H
18#define AAPT_VALUE_VISITOR_H
19
Adam Lesinski59e04c62016-02-04 15:59:23 -080020#include "ResourceTable.h"
Adam Lesinskicacb28f2016-10-19 12:18:14 -070021#include "ResourceValues.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070022
23namespace aapt {
24
Adam Lesinskid3ffa8442017-09-28 13:34:35 -070025// Visits a value and invokes the appropriate method based on its type.
26// Does not traverse into compound types. Use ValueVisitor for that.
27class ValueVisitor {
28 public:
29 virtual ~ValueVisitor() = default;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070030
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -080031 virtual void VisitAny(Value* value) {}
32 virtual void VisitItem(Item* value) { VisitAny(value); }
Adam Lesinskice5e56e2016-10-21 17:56:45 -070033 virtual void Visit(Reference* value) { VisitItem(value); }
34 virtual void Visit(RawString* value) { VisitItem(value); }
35 virtual void Visit(String* value) { VisitItem(value); }
36 virtual void Visit(StyledString* value) { VisitItem(value); }
37 virtual void Visit(FileReference* value) { VisitItem(value); }
38 virtual void Visit(Id* value) { VisitItem(value); }
39 virtual void Visit(BinaryPrimitive* value) { VisitItem(value); }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070040
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -080041 virtual void Visit(Attribute* value) { VisitAny(value); }
42 virtual void Visit(Style* value) { VisitAny(value); }
43 virtual void Visit(Array* value) { VisitAny(value); }
44 virtual void Visit(Plural* value) { VisitAny(value); }
45 virtual void Visit(Styleable* value) { VisitAny(value); }
Ryan Mitchell326e35ff2021-04-12 07:50:42 -070046 virtual void Visit(Macro* value) {
47 VisitAny(value);
48 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070049};
50
Adam Lesinskid3ffa8442017-09-28 13:34:35 -070051// Const version of ValueVisitor.
52class ConstValueVisitor {
53 public:
54 virtual ~ConstValueVisitor() = default;
55
56 virtual void VisitAny(const Value* value) {
57 }
58 virtual void VisitItem(const Item* value) {
59 VisitAny(value);
60 }
61 virtual void Visit(const Reference* value) {
62 VisitItem(value);
63 }
64 virtual void Visit(const RawString* value) {
65 VisitItem(value);
66 }
67 virtual void Visit(const String* value) {
68 VisitItem(value);
69 }
70 virtual void Visit(const StyledString* value) {
71 VisitItem(value);
72 }
73 virtual void Visit(const FileReference* value) {
74 VisitItem(value);
75 }
76 virtual void Visit(const Id* value) {
77 VisitItem(value);
78 }
79 virtual void Visit(const BinaryPrimitive* value) {
80 VisitItem(value);
81 }
82
83 virtual void Visit(const Attribute* value) {
84 VisitAny(value);
85 }
86 virtual void Visit(const Style* value) {
87 VisitAny(value);
88 }
89 virtual void Visit(const Array* value) {
90 VisitAny(value);
91 }
92 virtual void Visit(const Plural* value) {
93 VisitAny(value);
94 }
95 virtual void Visit(const Styleable* value) {
96 VisitAny(value);
97 }
Ryan Mitchell326e35ff2021-04-12 07:50:42 -070098 virtual void Visit(const Macro* value) {
99 VisitAny(value);
100 }
Adam Lesinskid3ffa8442017-09-28 13:34:35 -0700101};
102
Chih-Hung Hsieh470f8fc2016-08-15 12:32:51 -0700103// NOLINT, do not add parentheses around T.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700104#define DECL_VISIT_COMPOUND_VALUE(T) \
105 virtual void Visit(T* value) override { /* NOLINT */ \
106 VisitSubValues(value); \
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700107 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700108
Adam Lesinskid3ffa8442017-09-28 13:34:35 -0700109// Visits values, and if they are compound values, descends into their components as well.
110struct DescendingValueVisitor : public ValueVisitor {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700111 // The compiler will think we're hiding an overload, when we actually intend
112 // to call into RawValueVisitor. This will expose the visit methods in the
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700113 // super class so the compiler knows we are trying to call them.
Adam Lesinskid3ffa8442017-09-28 13:34:35 -0700114 using ValueVisitor::Visit;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700115
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700116 void VisitSubValues(Attribute* attribute) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700117 for (Attribute::Symbol& symbol : attribute->symbols) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700118 Visit(&symbol.symbol);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700119 }
120 }
121
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700122 void VisitSubValues(Style* style) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700123 if (style->parent) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700124 Visit(&style->parent.value());
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700125 }
126
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700127 for (Style::Entry& entry : style->entries) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700128 Visit(&entry.key);
129 entry.value->Accept(this);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700130 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700131 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700132
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700133 void VisitSubValues(Array* array) {
Adam Lesinski4ffea042017-08-10 15:37:28 -0700134 for (std::unique_ptr<Item>& item : array->elements) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700135 item->Accept(this);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700136 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700137 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700138
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700139 void VisitSubValues(Plural* plural) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700140 for (std::unique_ptr<Item>& item : plural->values) {
141 if (item) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700142 item->Accept(this);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700143 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700144 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700145 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700146
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700147 void VisitSubValues(Styleable* styleable) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700148 for (Reference& reference : styleable->entries) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700149 Visit(&reference);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700150 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700151 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700152
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700153 DECL_VISIT_COMPOUND_VALUE(Attribute);
154 DECL_VISIT_COMPOUND_VALUE(Style);
155 DECL_VISIT_COMPOUND_VALUE(Array);
156 DECL_VISIT_COMPOUND_VALUE(Plural);
157 DECL_VISIT_COMPOUND_VALUE(Styleable);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700158};
159
Adam Lesinskid3ffa8442017-09-28 13:34:35 -0700160// Do not use directly. Helper struct for dyn_cast.
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700161template <typename T>
Adam Lesinskid3ffa8442017-09-28 13:34:35 -0700162struct DynCastVisitor : public ConstValueVisitor {
163 const T* value = nullptr;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700164
Adam Lesinskid3ffa8442017-09-28 13:34:35 -0700165 void Visit(const T* v) override {
166 value = v;
167 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700168};
169
Adam Lesinskid3ffa8442017-09-28 13:34:35 -0700170// Specialization that checks if the value is an Item.
Adam Lesinskie78fd612015-10-22 12:48:43 -0700171template <>
Adam Lesinskid3ffa8442017-09-28 13:34:35 -0700172struct DynCastVisitor<Item> : public ConstValueVisitor {
173 const Item* value = nullptr;
Adam Lesinskie78fd612015-10-22 12:48:43 -0700174
Adam Lesinskid3ffa8442017-09-28 13:34:35 -0700175 void VisitItem(const Item* item) override {
176 value = item;
177 }
Adam Lesinskie78fd612015-10-22 12:48:43 -0700178};
179
Adam Lesinskid3ffa8442017-09-28 13:34:35 -0700180// Returns a valid pointer to T if the value is an instance of T. Returns nullptr if value is
181// nullptr of if value is not an instance of T.
Adam Lesinski458b8772016-04-25 14:20:21 -0700182template <typename T>
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700183const T* ValueCast(const Value* value) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700184 if (!value) {
185 return nullptr;
186 }
187 DynCastVisitor<T> visitor;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700188 value->Accept(&visitor);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700189 return visitor.value;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700190}
191
Adam Lesinskid3ffa8442017-09-28 13:34:35 -0700192// Non-const version of ValueCast.
193template <typename T>
194T* ValueCast(Value* value) {
195 return const_cast<T*>(ValueCast<T>(static_cast<const Value*>(value)));
196}
197
198inline void VisitAllValuesInPackage(ResourceTablePackage* pkg, ValueVisitor* visitor) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700199 for (auto& type : pkg->types) {
200 for (auto& entry : type->entries) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700201 for (auto& config_value : entry->values) {
202 config_value->value->Accept(visitor);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700203 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800204 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700205 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800206}
207
Adam Lesinskid3ffa8442017-09-28 13:34:35 -0700208inline void VisitAllValuesInTable(ResourceTable* table, ValueVisitor* visitor) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700209 for (auto& pkg : table->packages) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700210 VisitAllValuesInPackage(pkg.get(), visitor);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700211 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800212}
213
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700214} // namespace aapt
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700215
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700216#endif // AAPT_VALUE_VISITOR_H