blob: eb4fa494e53f32497aad0ebc13d902ee4eca0c70 [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
Adam Lesinskice5e56e2016-10-21 17:56:45 -070027 * traverse into compound types. Use ValueVisitor for that.
Adam Lesinski1ab598f2015-08-14 14:26:04 -070028 */
29struct RawValueVisitor {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070030 virtual ~RawValueVisitor() = default;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070031
Adam Lesinskiceb9b2f2017-02-16 12:05:42 -080032 virtual void VisitAny(Value* value) {}
33 virtual void VisitItem(Item* value) { VisitAny(value); }
Adam Lesinskice5e56e2016-10-21 17:56:45 -070034 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 Lesinskiceb9b2f2017-02-16 12:05:42 -080042 virtual void Visit(Attribute* value) { VisitAny(value); }
43 virtual void Visit(Style* value) { VisitAny(value); }
44 virtual void Visit(Array* value) { VisitAny(value); }
45 virtual void Visit(Plural* value) { VisitAny(value); }
46 virtual void Visit(Styleable* value) { VisitAny(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 Lesinskice5e56e2016-10-21 17:56:45 -070050#define DECL_VISIT_COMPOUND_VALUE(T) \
51 virtual void Visit(T* value) override { /* NOLINT */ \
52 VisitSubValues(value); \
Adam Lesinskicacb28f2016-10-19 12:18:14 -070053 }
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
Adam Lesinskice5e56e2016-10-21 17:56:45 -070062 // super class so the compiler knows we are trying to call them.
63 using RawValueVisitor::Visit;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070064
Adam Lesinskice5e56e2016-10-21 17:56:45 -070065 void VisitSubValues(Attribute* attribute) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070066 for (Attribute::Symbol& symbol : attribute->symbols) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070067 Visit(&symbol.symbol);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070068 }
69 }
70
Adam Lesinskice5e56e2016-10-21 17:56:45 -070071 void VisitSubValues(Style* style) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070072 if (style->parent) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070073 Visit(&style->parent.value());
Adam Lesinski1ab598f2015-08-14 14:26:04 -070074 }
75
Adam Lesinskicacb28f2016-10-19 12:18:14 -070076 for (Style::Entry& entry : style->entries) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070077 Visit(&entry.key);
78 entry.value->Accept(this);
Adam Lesinski1ab598f2015-08-14 14:26:04 -070079 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070080 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070081
Adam Lesinskice5e56e2016-10-21 17:56:45 -070082 void VisitSubValues(Array* array) {
Adam Lesinski4ffea042017-08-10 15:37:28 -070083 for (std::unique_ptr<Item>& item : array->elements) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070084 item->Accept(this);
Adam Lesinski1ab598f2015-08-14 14:26:04 -070085 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070086 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070087
Adam Lesinskice5e56e2016-10-21 17:56:45 -070088 void VisitSubValues(Plural* plural) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070089 for (std::unique_ptr<Item>& item : plural->values) {
90 if (item) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070091 item->Accept(this);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070092 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070093 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070094 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070095
Adam Lesinskice5e56e2016-10-21 17:56:45 -070096 void VisitSubValues(Styleable* styleable) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070097 for (Reference& reference : styleable->entries) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070098 Visit(&reference);
Adam Lesinski1ab598f2015-08-14 14:26:04 -070099 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700100 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700101
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700102 DECL_VISIT_COMPOUND_VALUE(Attribute);
103 DECL_VISIT_COMPOUND_VALUE(Style);
104 DECL_VISIT_COMPOUND_VALUE(Array);
105 DECL_VISIT_COMPOUND_VALUE(Plural);
106 DECL_VISIT_COMPOUND_VALUE(Styleable);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700107};
108
109/**
110 * Do not use directly. Helper struct for dyn_cast.
111 */
112template <typename T>
113struct DynCastVisitor : public RawValueVisitor {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700114 T* value = nullptr;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700115
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700116 void Visit(T* v) override { value = v; }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700117};
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 {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700124 Item* value = nullptr;
Adam Lesinskie78fd612015-10-22 12:48:43 -0700125
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700126 void VisitItem(Item* item) override { value = item; }
Adam Lesinskie78fd612015-10-22 12:48:43 -0700127};
128
Adam Lesinski458b8772016-04-25 14:20:21 -0700129template <typename T>
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700130const T* ValueCast(const Value* value) {
131 return ValueCast<T>(const_cast<Value*>(value));
Adam Lesinski458b8772016-04-25 14:20:21 -0700132}
133
Adam Lesinskie78fd612015-10-22 12:48:43 -0700134/**
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700135 * Returns a valid pointer to T if the Value is of subtype T.
136 * Otherwise, returns nullptr.
137 */
138template <typename T>
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700139T* ValueCast(Value* value) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700140 if (!value) {
141 return nullptr;
142 }
143 DynCastVisitor<T> visitor;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700144 value->Accept(&visitor);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700145 return visitor.value;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700146}
147
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700148inline void VisitAllValuesInPackage(ResourceTablePackage* pkg,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700149 RawValueVisitor* visitor) {
150 for (auto& type : pkg->types) {
151 for (auto& entry : type->entries) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700152 for (auto& config_value : entry->values) {
153 config_value->value->Accept(visitor);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700154 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800155 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700156 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800157}
158
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700159inline void VisitAllValuesInTable(ResourceTable* table,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700160 RawValueVisitor* visitor) {
161 for (auto& pkg : table->packages) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700162 VisitAllValuesInPackage(pkg.get(), visitor);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700163 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800164}
165
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700166} // namespace aapt
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700167
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700168#endif // AAPT_VALUE_VISITOR_H