blob: 1cb6aa13f336fecc4ca6b856db40e5e6401c928e [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 Lesinskice5e56e2016-10-21 17:56:45 -070032 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); }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070040
Adam Lesinskice5e56e2016-10-21 17:56:45 -070041 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) {}
Adam Lesinski1ab598f2015-08-14 14:26:04 -070046};
47
Chih-Hung Hsieh470f8fc2016-08-15 12:32:51 -070048// NOLINT, do not add parentheses around T.
Adam Lesinskice5e56e2016-10-21 17:56:45 -070049#define DECL_VISIT_COMPOUND_VALUE(T) \
50 virtual void Visit(T* value) override { /* NOLINT */ \
51 VisitSubValues(value); \
Adam Lesinskicacb28f2016-10-19 12:18:14 -070052 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070053
54/**
Adam Lesinskicacb28f2016-10-19 12:18:14 -070055 * Visits values, and if they are compound values, visits the components as
56 * well.
Adam Lesinski1ab598f2015-08-14 14:26:04 -070057 */
58struct ValueVisitor : public RawValueVisitor {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070059 // The compiler will think we're hiding an overload, when we actually intend
60 // to call into RawValueVisitor. This will expose the visit methods in the
Adam Lesinskice5e56e2016-10-21 17:56:45 -070061 // super class so the compiler knows we are trying to call them.
62 using RawValueVisitor::Visit;
Adam Lesinski1ab598f2015-08-14 14:26:04 -070063
Adam Lesinskice5e56e2016-10-21 17:56:45 -070064 void VisitSubValues(Attribute* attribute) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070065 for (Attribute::Symbol& symbol : attribute->symbols) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070066 Visit(&symbol.symbol);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070067 }
68 }
69
Adam Lesinskice5e56e2016-10-21 17:56:45 -070070 void VisitSubValues(Style* style) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070071 if (style->parent) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070072 Visit(&style->parent.value());
Adam Lesinski1ab598f2015-08-14 14:26:04 -070073 }
74
Adam Lesinskicacb28f2016-10-19 12:18:14 -070075 for (Style::Entry& entry : style->entries) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070076 Visit(&entry.key);
77 entry.value->Accept(this);
Adam Lesinski1ab598f2015-08-14 14:26:04 -070078 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070079 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070080
Adam Lesinskice5e56e2016-10-21 17:56:45 -070081 void VisitSubValues(Array* array) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070082 for (std::unique_ptr<Item>& item : array->items) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070083 item->Accept(this);
Adam Lesinski1ab598f2015-08-14 14:26:04 -070084 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070085 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070086
Adam Lesinskice5e56e2016-10-21 17:56:45 -070087 void VisitSubValues(Plural* plural) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070088 for (std::unique_ptr<Item>& item : plural->values) {
89 if (item) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070090 item->Accept(this);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070091 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070092 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070093 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -070094
Adam Lesinskice5e56e2016-10-21 17:56:45 -070095 void VisitSubValues(Styleable* styleable) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070096 for (Reference& reference : styleable->entries) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070097 Visit(&reference);
Adam Lesinski1ab598f2015-08-14 14:26:04 -070098 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -070099 }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700100
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700101 DECL_VISIT_COMPOUND_VALUE(Attribute);
102 DECL_VISIT_COMPOUND_VALUE(Style);
103 DECL_VISIT_COMPOUND_VALUE(Array);
104 DECL_VISIT_COMPOUND_VALUE(Plural);
105 DECL_VISIT_COMPOUND_VALUE(Styleable);
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700106};
107
108/**
109 * Do not use directly. Helper struct for dyn_cast.
110 */
111template <typename T>
112struct DynCastVisitor : public RawValueVisitor {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700113 T* value = nullptr;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700114
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700115 void Visit(T* v) override { value = v; }
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700116};
117
118/**
Adam Lesinskie78fd612015-10-22 12:48:43 -0700119 * Specialization that checks if the value is an Item.
120 */
121template <>
122struct DynCastVisitor<Item> : public RawValueVisitor {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700123 Item* value = nullptr;
Adam Lesinskie78fd612015-10-22 12:48:43 -0700124
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700125 void VisitItem(Item* item) override { value = item; }
Adam Lesinskie78fd612015-10-22 12:48:43 -0700126};
127
Adam Lesinski458b8772016-04-25 14:20:21 -0700128template <typename T>
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700129const T* ValueCast(const Value* value) {
130 return ValueCast<T>(const_cast<Value*>(value));
Adam Lesinski458b8772016-04-25 14:20:21 -0700131}
132
Adam Lesinskie78fd612015-10-22 12:48:43 -0700133/**
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700134 * Returns a valid pointer to T if the Value is of subtype T.
135 * Otherwise, returns nullptr.
136 */
137template <typename T>
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700138T* ValueCast(Value* value) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700139 if (!value) {
140 return nullptr;
141 }
142 DynCastVisitor<T> visitor;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700143 value->Accept(&visitor);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700144 return visitor.value;
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700145}
146
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700147inline void VisitAllValuesInPackage(ResourceTablePackage* pkg,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700148 RawValueVisitor* visitor) {
149 for (auto& type : pkg->types) {
150 for (auto& entry : type->entries) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700151 for (auto& config_value : entry->values) {
152 config_value->value->Accept(visitor);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700153 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800154 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700155 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800156}
157
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700158inline void VisitAllValuesInTable(ResourceTable* table,
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700159 RawValueVisitor* visitor) {
160 for (auto& pkg : table->packages) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700161 VisitAllValuesInPackage(pkg.get(), visitor);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700162 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800163}
164
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700165} // namespace aapt
Adam Lesinski1ab598f2015-08-14 14:26:04 -0700166
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700167#endif // AAPT_VALUE_VISITOR_H