blob: 121c33709eefefabd85c899875835b068452c97a [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
25/**
Adam Lesinskicacb28f2016-10-19 12:18:14 -070026 * Visits a value and invokes the appropriate method based on its type. Does not
27 * traverse
Adam Lesinski1ab598f2015-08-14 14:26:04 -070028 * into compound types. Use ValueVisitor for that.
29 */
30struct RawValueVisitor {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070031 virtual ~RawValueVisitor() = default;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070032
Adam Lesinskicacb28f2016-10-19 12:18:14 -070033 virtual void visitItem(Item* value) {}
34 virtual void visit(Reference* value) { visitItem(value); }
35 virtual void visit(RawString* value) { visitItem(value); }
36 virtual void visit(String* value) { visitItem(value); }
37 virtual void visit(StyledString* value) { visitItem(value); }
38 virtual void visit(FileReference* value) { visitItem(value); }
39 virtual void visit(Id* value) { visitItem(value); }
40 virtual void visit(BinaryPrimitive* value) { visitItem(value); }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070041
Adam Lesinskicacb28f2016-10-19 12:18:14 -070042 virtual void visit(Attribute* value) {}
43 virtual void visit(Style* value) {}
44 virtual void visit(Array* value) {}
45 virtual void visit(Plural* value) {}
46 virtual void visit(Styleable* value) {}
Adam Lesinski1ab598f2015-08-14 14:26:04 -070047};
48
Chih-Hung Hsieh470f8fc2016-08-15 12:32:51 -070049// NOLINT, do not add parentheses around T.
Adam Lesinskicacb28f2016-10-19 12:18:14 -070050#define DECL_VISIT_COMPOUND_VALUE(T) \
51 virtual void visit(T* value) { /* NOLINT */ \
52 visitSubValues(value); \
53 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070054
55/**
Adam Lesinskicacb28f2016-10-19 12:18:14 -070056 * Visits values, and if they are compound values, visits the components as
57 * well.
Adam Lesinski1ab598f2015-08-14 14:26:04 -070058 */
59struct ValueVisitor : public RawValueVisitor {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070060 // The compiler will think we're hiding an overload, when we actually intend
61 // to call into RawValueVisitor. This will expose the visit methods in the
62 // super
63 // class so the compiler knows we are trying to call them.
64 using RawValueVisitor::visit;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070065
Adam Lesinskicacb28f2016-10-19 12:18:14 -070066 void visitSubValues(Attribute* attribute) {
67 for (Attribute::Symbol& symbol : attribute->symbols) {
68 visit(&symbol.symbol);
69 }
70 }
71
72 void visitSubValues(Style* style) {
73 if (style->parent) {
74 visit(&style->parent.value());
Adam Lesinski1ab598f2015-08-14 14:26:04 -070075 }
76
Adam Lesinskicacb28f2016-10-19 12:18:14 -070077 for (Style::Entry& entry : style->entries) {
78 visit(&entry.key);
79 entry.value->accept(this);
Adam Lesinski1ab598f2015-08-14 14:26:04 -070080 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070081 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070082
Adam Lesinskicacb28f2016-10-19 12:18:14 -070083 void visitSubValues(Array* array) {
84 for (std::unique_ptr<Item>& item : array->items) {
85 item->accept(this);
Adam Lesinski1ab598f2015-08-14 14:26:04 -070086 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070087 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070088
Adam Lesinskicacb28f2016-10-19 12:18:14 -070089 void visitSubValues(Plural* plural) {
90 for (std::unique_ptr<Item>& item : plural->values) {
91 if (item) {
92 item->accept(this);
93 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070094 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070095 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070096
Adam Lesinskicacb28f2016-10-19 12:18:14 -070097 void visitSubValues(Styleable* styleable) {
98 for (Reference& reference : styleable->entries) {
99 visit(&reference);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700100 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700101 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700102
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700103 DECL_VISIT_COMPOUND_VALUE(Attribute);
104 DECL_VISIT_COMPOUND_VALUE(Style);
105 DECL_VISIT_COMPOUND_VALUE(Array);
106 DECL_VISIT_COMPOUND_VALUE(Plural);
107 DECL_VISIT_COMPOUND_VALUE(Styleable);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700108};
109
110/**
111 * Do not use directly. Helper struct for dyn_cast.
112 */
113template <typename T>
114struct DynCastVisitor : public RawValueVisitor {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700115 T* value = nullptr;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700116
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700117 void visit(T* v) override { value = v; }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700118};
119
120/**
Adam Lesinskie78fd612015-10-22 12:48:43 -0700121 * Specialization that checks if the value is an Item.
122 */
123template <>
124struct DynCastVisitor<Item> : public RawValueVisitor {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700125 Item* value = nullptr;
Adam Lesinskie78fd612015-10-22 12:48:43 -0700126
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700127 void visitItem(Item* item) override { value = item; }
Adam Lesinskie78fd612015-10-22 12:48:43 -0700128};
129
Adam Lesinski458b8772016-04-25 14:20:21 -0700130template <typename T>
131const T* valueCast(const Value* value) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700132 return valueCast<T>(const_cast<Value*>(value));
Adam Lesinski458b8772016-04-25 14:20:21 -0700133}
134
Adam Lesinskie78fd612015-10-22 12:48:43 -0700135/**
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700136 * Returns a valid pointer to T if the Value is of subtype T.
137 * Otherwise, returns nullptr.
138 */
139template <typename T>
140T* valueCast(Value* value) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700141 if (!value) {
142 return nullptr;
143 }
144 DynCastVisitor<T> visitor;
145 value->accept(&visitor);
146 return visitor.value;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700147}
148
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700149inline void visitAllValuesInPackage(ResourceTablePackage* pkg,
150 RawValueVisitor* visitor) {
151 for (auto& type : pkg->types) {
152 for (auto& entry : type->entries) {
153 for (auto& configValue : entry->values) {
154 configValue->value->accept(visitor);
155 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800156 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700157 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800158}
159
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700160inline void visitAllValuesInTable(ResourceTable* table,
161 RawValueVisitor* visitor) {
162 for (auto& pkg : table->packages) {
163 visitAllValuesInPackage(pkg.get(), visitor);
164 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800165}
166
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700167} // namespace aapt
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700168
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700169#endif // AAPT_VALUE_VISITOR_H