blob: 9dc6a9c2b0d2adb02f374a109bf057e0869213f6 [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
20#include "ResourceValues.h"
Adam Lesinski59e04c62016-02-04 15:59:23 -080021#include "ResourceTable.h"
Adam Lesinski1ab598f2015-08-14 14:26:04 -070022
23namespace aapt {
24
25/**
26 * Visits a value and invokes the appropriate method based on its type. Does not traverse
27 * into compound types. Use ValueVisitor for that.
28 */
29struct RawValueVisitor {
30 virtual ~RawValueVisitor() = default;
31
32 virtual void visitItem(Item* value) {}
33 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); }
40
41 virtual void visit(Attribute* value) {}
42 virtual void visit(Style* value) {}
43 virtual void visit(Array* value) {}
44 virtual void visit(Plural* value) {}
45 virtual void visit(Styleable* value) {}
46};
47
Chih-Hung Hsieh470f8fc2016-08-15 12:32:51 -070048// NOLINT, do not add parentheses around T.
Adam Lesinski1ab598f2015-08-14 14:26:04 -070049#define DECL_VISIT_COMPOUND_VALUE(T) \
Chih-Hung Hsieh470f8fc2016-08-15 12:32:51 -070050 virtual void visit(T* value) { /* NOLINT */ \
Adam Lesinski1ab598f2015-08-14 14:26:04 -070051 visitSubValues(value); \
52 }
53
54/**
55 * Visits values, and if they are compound values, visits the components as well.
56 */
57struct ValueVisitor : public RawValueVisitor {
58 // The compiler will think we're hiding an overload, when we actually intend
59 // to call into RawValueVisitor. This will expose the visit methods in the super
60 // class so the compiler knows we are trying to call them.
61 using RawValueVisitor::visit;
62
63 void visitSubValues(Attribute* attribute) {
64 for (Attribute::Symbol& symbol : attribute->symbols) {
65 visit(&symbol.symbol);
66 }
67 }
68
69 void visitSubValues(Style* style) {
70 if (style->parent) {
71 visit(&style->parent.value());
72 }
73
74 for (Style::Entry& entry : style->entries) {
75 visit(&entry.key);
76 entry.value->accept(this);
77 }
78 }
79
80 void visitSubValues(Array* array) {
81 for (std::unique_ptr<Item>& item : array->items) {
82 item->accept(this);
83 }
84 }
85
86 void visitSubValues(Plural* plural) {
87 for (std::unique_ptr<Item>& item : plural->values) {
88 if (item) {
89 item->accept(this);
90 }
91 }
92 }
93
94 void visitSubValues(Styleable* styleable) {
95 for (Reference& reference : styleable->entries) {
96 visit(&reference);
97 }
98 }
99
100 DECL_VISIT_COMPOUND_VALUE(Attribute);
101 DECL_VISIT_COMPOUND_VALUE(Style);
102 DECL_VISIT_COMPOUND_VALUE(Array);
103 DECL_VISIT_COMPOUND_VALUE(Plural);
104 DECL_VISIT_COMPOUND_VALUE(Styleable);
105};
106
107/**
108 * Do not use directly. Helper struct for dyn_cast.
109 */
110template <typename T>
111struct DynCastVisitor : public RawValueVisitor {
112 T* value = nullptr;
113
114 void visit(T* v) override {
115 value = v;
116 }
117};
118
119/**
Adam Lesinskie78fd612015-10-22 12:48:43 -0700120 * Specialization that checks if the value is an Item.
121 */
122template <>
123struct DynCastVisitor<Item> : public RawValueVisitor {
124 Item* value = nullptr;
125
126 void visitItem(Item* item) override {
127 value = item;
128 }
129};
130
Adam Lesinski458b8772016-04-25 14:20:21 -0700131template <typename T>
132const T* valueCast(const Value* value) {
133 return valueCast<T>(const_cast<Value*>(value));
134}
135
Adam Lesinskie78fd612015-10-22 12:48:43 -0700136/**
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700137 * Returns a valid pointer to T if the Value is of subtype T.
138 * Otherwise, returns nullptr.
139 */
140template <typename T>
141T* valueCast(Value* value) {
142 if (!value) {
143 return nullptr;
144 }
145 DynCastVisitor<T> visitor;
146 value->accept(&visitor);
147 return visitor.value;
148}
149
Adam Lesinski59e04c62016-02-04 15:59:23 -0800150inline void visitAllValuesInPackage(ResourceTablePackage* pkg, RawValueVisitor* visitor) {
151 for (auto& type : pkg->types) {
152 for (auto& entry : type->entries) {
153 for (auto& configValue : entry->values) {
Adam Lesinskie4bb9eb2016-02-12 22:18:51 -0800154 configValue->value->accept(visitor);
Adam Lesinski59e04c62016-02-04 15:59:23 -0800155 }
156 }
157 }
158}
159
160inline void visitAllValuesInTable(ResourceTable* table, RawValueVisitor* visitor) {
161 for (auto& pkg : table->packages) {
162 visitAllValuesInPackage(pkg.get(), visitor);
163 }
164}
165
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700166} // namespace aapt
167
168#endif // AAPT_VALUE_VISITOR_H