blob: ee058aa1a37b6cf29cd4d9892d2d674b75f1fff0 [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"
21
22namespace aapt {
23
24/**
25 * Visits a value and invokes the appropriate method based on its type. Does not traverse
26 * into compound types. Use ValueVisitor for that.
27 */
28struct RawValueVisitor {
29 virtual ~RawValueVisitor() = default;
30
31 virtual void visitItem(Item* value) {}
32 virtual void visit(Reference* value) { visitItem(value); }
33 virtual void visit(RawString* value) { visitItem(value); }
34 virtual void visit(String* value) { visitItem(value); }
35 virtual void visit(StyledString* value) { visitItem(value); }
36 virtual void visit(FileReference* value) { visitItem(value); }
37 virtual void visit(Id* value) { visitItem(value); }
38 virtual void visit(BinaryPrimitive* value) { visitItem(value); }
39
40 virtual void visit(Attribute* value) {}
41 virtual void visit(Style* value) {}
42 virtual void visit(Array* value) {}
43 virtual void visit(Plural* value) {}
44 virtual void visit(Styleable* value) {}
45};
46
47#define DECL_VISIT_COMPOUND_VALUE(T) \
48 virtual void visit(T* value) { \
49 visitSubValues(value); \
50 }
51
52/**
53 * Visits values, and if they are compound values, visits the components as well.
54 */
55struct ValueVisitor : public RawValueVisitor {
56 // The compiler will think we're hiding an overload, when we actually intend
57 // to call into RawValueVisitor. This will expose the visit methods in the super
58 // class so the compiler knows we are trying to call them.
59 using RawValueVisitor::visit;
60
61 void visitSubValues(Attribute* attribute) {
62 for (Attribute::Symbol& symbol : attribute->symbols) {
63 visit(&symbol.symbol);
64 }
65 }
66
67 void visitSubValues(Style* style) {
68 if (style->parent) {
69 visit(&style->parent.value());
70 }
71
72 for (Style::Entry& entry : style->entries) {
73 visit(&entry.key);
74 entry.value->accept(this);
75 }
76 }
77
78 void visitSubValues(Array* array) {
79 for (std::unique_ptr<Item>& item : array->items) {
80 item->accept(this);
81 }
82 }
83
84 void visitSubValues(Plural* plural) {
85 for (std::unique_ptr<Item>& item : plural->values) {
86 if (item) {
87 item->accept(this);
88 }
89 }
90 }
91
92 void visitSubValues(Styleable* styleable) {
93 for (Reference& reference : styleable->entries) {
94 visit(&reference);
95 }
96 }
97
98 DECL_VISIT_COMPOUND_VALUE(Attribute);
99 DECL_VISIT_COMPOUND_VALUE(Style);
100 DECL_VISIT_COMPOUND_VALUE(Array);
101 DECL_VISIT_COMPOUND_VALUE(Plural);
102 DECL_VISIT_COMPOUND_VALUE(Styleable);
103};
104
105/**
106 * Do not use directly. Helper struct for dyn_cast.
107 */
108template <typename T>
109struct DynCastVisitor : public RawValueVisitor {
110 T* value = nullptr;
111
112 void visit(T* v) override {
113 value = v;
114 }
115};
116
117/**
118 * Returns a valid pointer to T if the Value is of subtype T.
119 * Otherwise, returns nullptr.
120 */
121template <typename T>
122T* valueCast(Value* value) {
123 if (!value) {
124 return nullptr;
125 }
126 DynCastVisitor<T> visitor;
127 value->accept(&visitor);
128 return visitor.value;
129}
130
131} // namespace aapt
132
133#endif // AAPT_VALUE_VISITOR_H