• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 #include "ResourceTable.h"
22 
23 namespace 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  */
29 struct RawValueVisitor {
30     virtual ~RawValueVisitor() = default;
31 
visitItemRawValueVisitor32     virtual void visitItem(Item* value) {}
visitRawValueVisitor33     virtual void visit(Reference* value) { visitItem(value); }
visitRawValueVisitor34     virtual void visit(RawString* value) { visitItem(value); }
visitRawValueVisitor35     virtual void visit(String* value) { visitItem(value); }
visitRawValueVisitor36     virtual void visit(StyledString* value) { visitItem(value); }
visitRawValueVisitor37     virtual void visit(FileReference* value) { visitItem(value); }
visitRawValueVisitor38     virtual void visit(Id* value) { visitItem(value); }
visitRawValueVisitor39     virtual void visit(BinaryPrimitive* value) { visitItem(value); }
40 
visitRawValueVisitor41     virtual void visit(Attribute* value) {}
visitRawValueVisitor42     virtual void visit(Style* value) {}
visitRawValueVisitor43     virtual void visit(Array* value) {}
visitRawValueVisitor44     virtual void visit(Plural* value) {}
visitRawValueVisitor45     virtual void visit(Styleable* value) {}
46 };
47 
48 #define DECL_VISIT_COMPOUND_VALUE(T) \
49     virtual void visit(T* value) { \
50         visitSubValues(value); \
51     }
52 
53 /**
54  * Visits values, and if they are compound values, visits the components as well.
55  */
56 struct ValueVisitor : public RawValueVisitor {
57     // The compiler will think we're hiding an overload, when we actually intend
58     // to call into RawValueVisitor. This will expose the visit methods in the super
59     // class so the compiler knows we are trying to call them.
60     using RawValueVisitor::visit;
61 
visitSubValuesValueVisitor62     void visitSubValues(Attribute* attribute) {
63         for (Attribute::Symbol& symbol : attribute->symbols) {
64             visit(&symbol.symbol);
65         }
66     }
67 
visitSubValuesValueVisitor68     void visitSubValues(Style* style) {
69         if (style->parent) {
70             visit(&style->parent.value());
71         }
72 
73         for (Style::Entry& entry : style->entries) {
74             visit(&entry.key);
75             entry.value->accept(this);
76         }
77     }
78 
visitSubValuesValueVisitor79     void visitSubValues(Array* array) {
80         for (std::unique_ptr<Item>& item : array->items) {
81             item->accept(this);
82         }
83     }
84 
visitSubValuesValueVisitor85     void visitSubValues(Plural* plural) {
86         for (std::unique_ptr<Item>& item : plural->values) {
87             if (item) {
88                 item->accept(this);
89             }
90         }
91     }
92 
visitSubValuesValueVisitor93     void visitSubValues(Styleable* styleable) {
94         for (Reference& reference : styleable->entries) {
95             visit(&reference);
96         }
97     }
98 
99     DECL_VISIT_COMPOUND_VALUE(Attribute);
100     DECL_VISIT_COMPOUND_VALUE(Style);
101     DECL_VISIT_COMPOUND_VALUE(Array);
102     DECL_VISIT_COMPOUND_VALUE(Plural);
103     DECL_VISIT_COMPOUND_VALUE(Styleable);
104 };
105 
106 /**
107  * Do not use directly. Helper struct for dyn_cast.
108  */
109 template <typename T>
110 struct DynCastVisitor : public RawValueVisitor {
111     T* value = nullptr;
112 
visitDynCastVisitor113     void visit(T* v) override {
114         value = v;
115     }
116 };
117 
118 /**
119  * Specialization that checks if the value is an Item.
120  */
121 template <>
122 struct DynCastVisitor<Item> : public RawValueVisitor {
123     Item* value = nullptr;
124 
125     void visitItem(Item* item) override {
126         value = item;
127     }
128 };
129 
130 template <typename T>
131 const T* valueCast(const Value* value) {
132     return valueCast<T>(const_cast<Value*>(value));
133 }
134 
135 /**
136  * Returns a valid pointer to T if the Value is of subtype T.
137  * Otherwise, returns nullptr.
138  */
139 template <typename T>
140 T* valueCast(Value* value) {
141     if (!value) {
142         return nullptr;
143     }
144     DynCastVisitor<T> visitor;
145     value->accept(&visitor);
146     return visitor.value;
147 }
148 
149 inline void visitAllValuesInPackage(ResourceTablePackage* pkg, RawValueVisitor* visitor) {
150     for (auto& type : pkg->types) {
151         for (auto& entry : type->entries) {
152             for (auto& configValue : entry->values) {
153                 configValue->value->accept(visitor);
154             }
155         }
156     }
157 }
158 
159 inline void visitAllValuesInTable(ResourceTable* table, RawValueVisitor* visitor) {
160     for (auto& pkg : table->packages) {
161         visitAllValuesInPackage(pkg.get(), visitor);
162     }
163 }
164 
165 } // namespace aapt
166 
167 #endif // AAPT_VALUE_VISITOR_H
168