xref: /aosp_15_r20/frameworks/base/tools/aapt2/ValueVisitor.h (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker  *
4*d57664e9SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker  *
8*d57664e9SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker  *
10*d57664e9SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker  * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker  */
16*d57664e9SAndroid Build Coastguard Worker 
17*d57664e9SAndroid Build Coastguard Worker #ifndef AAPT_VALUE_VISITOR_H
18*d57664e9SAndroid Build Coastguard Worker #define AAPT_VALUE_VISITOR_H
19*d57664e9SAndroid Build Coastguard Worker 
20*d57664e9SAndroid Build Coastguard Worker #include "ResourceTable.h"
21*d57664e9SAndroid Build Coastguard Worker #include "ResourceValues.h"
22*d57664e9SAndroid Build Coastguard Worker 
23*d57664e9SAndroid Build Coastguard Worker namespace aapt {
24*d57664e9SAndroid Build Coastguard Worker 
25*d57664e9SAndroid Build Coastguard Worker // Visits a value and invokes the appropriate method based on its type.
26*d57664e9SAndroid Build Coastguard Worker // Does not traverse into compound types. Use ValueVisitor for that.
27*d57664e9SAndroid Build Coastguard Worker class ValueVisitor {
28*d57664e9SAndroid Build Coastguard Worker  public:
29*d57664e9SAndroid Build Coastguard Worker   virtual ~ValueVisitor() = default;
30*d57664e9SAndroid Build Coastguard Worker 
VisitAny(Value * value)31*d57664e9SAndroid Build Coastguard Worker   virtual void VisitAny(Value* value) {}
VisitItem(Item * value)32*d57664e9SAndroid Build Coastguard Worker   virtual void VisitItem(Item* value) { VisitAny(value); }
Visit(Reference * value)33*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(Reference* value) { VisitItem(value); }
Visit(RawString * value)34*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(RawString* value) { VisitItem(value); }
Visit(String * value)35*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(String* value) { VisitItem(value); }
Visit(StyledString * value)36*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(StyledString* value) { VisitItem(value); }
Visit(FileReference * value)37*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(FileReference* value) { VisitItem(value); }
Visit(Id * value)38*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(Id* value) { VisitItem(value); }
Visit(BinaryPrimitive * value)39*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(BinaryPrimitive* value) { VisitItem(value); }
40*d57664e9SAndroid Build Coastguard Worker 
Visit(Attribute * value)41*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(Attribute* value) { VisitAny(value); }
Visit(Style * value)42*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(Style* value) { VisitAny(value); }
Visit(Array * value)43*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(Array* value) { VisitAny(value); }
Visit(Plural * value)44*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(Plural* value) { VisitAny(value); }
Visit(Styleable * value)45*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(Styleable* value) { VisitAny(value); }
Visit(Macro * value)46*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(Macro* value) {
47*d57664e9SAndroid Build Coastguard Worker     VisitAny(value);
48*d57664e9SAndroid Build Coastguard Worker   }
49*d57664e9SAndroid Build Coastguard Worker };
50*d57664e9SAndroid Build Coastguard Worker 
51*d57664e9SAndroid Build Coastguard Worker // Const version of ValueVisitor.
52*d57664e9SAndroid Build Coastguard Worker class ConstValueVisitor {
53*d57664e9SAndroid Build Coastguard Worker  public:
54*d57664e9SAndroid Build Coastguard Worker   virtual ~ConstValueVisitor() = default;
55*d57664e9SAndroid Build Coastguard Worker 
VisitAny(const Value * value)56*d57664e9SAndroid Build Coastguard Worker   virtual void VisitAny(const Value* value) {
57*d57664e9SAndroid Build Coastguard Worker   }
VisitItem(const Item * value)58*d57664e9SAndroid Build Coastguard Worker   virtual void VisitItem(const Item* value) {
59*d57664e9SAndroid Build Coastguard Worker     VisitAny(value);
60*d57664e9SAndroid Build Coastguard Worker   }
Visit(const Reference * value)61*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(const Reference* value) {
62*d57664e9SAndroid Build Coastguard Worker     VisitItem(value);
63*d57664e9SAndroid Build Coastguard Worker   }
Visit(const RawString * value)64*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(const RawString* value) {
65*d57664e9SAndroid Build Coastguard Worker     VisitItem(value);
66*d57664e9SAndroid Build Coastguard Worker   }
Visit(const String * value)67*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(const String* value) {
68*d57664e9SAndroid Build Coastguard Worker     VisitItem(value);
69*d57664e9SAndroid Build Coastguard Worker   }
Visit(const StyledString * value)70*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(const StyledString* value) {
71*d57664e9SAndroid Build Coastguard Worker     VisitItem(value);
72*d57664e9SAndroid Build Coastguard Worker   }
Visit(const FileReference * value)73*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(const FileReference* value) {
74*d57664e9SAndroid Build Coastguard Worker     VisitItem(value);
75*d57664e9SAndroid Build Coastguard Worker   }
Visit(const Id * value)76*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(const Id* value) {
77*d57664e9SAndroid Build Coastguard Worker     VisitItem(value);
78*d57664e9SAndroid Build Coastguard Worker   }
Visit(const BinaryPrimitive * value)79*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(const BinaryPrimitive* value) {
80*d57664e9SAndroid Build Coastguard Worker     VisitItem(value);
81*d57664e9SAndroid Build Coastguard Worker   }
82*d57664e9SAndroid Build Coastguard Worker 
Visit(const Attribute * value)83*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(const Attribute* value) {
84*d57664e9SAndroid Build Coastguard Worker     VisitAny(value);
85*d57664e9SAndroid Build Coastguard Worker   }
Visit(const Style * value)86*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(const Style* value) {
87*d57664e9SAndroid Build Coastguard Worker     VisitAny(value);
88*d57664e9SAndroid Build Coastguard Worker   }
Visit(const Array * value)89*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(const Array* value) {
90*d57664e9SAndroid Build Coastguard Worker     VisitAny(value);
91*d57664e9SAndroid Build Coastguard Worker   }
Visit(const Plural * value)92*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(const Plural* value) {
93*d57664e9SAndroid Build Coastguard Worker     VisitAny(value);
94*d57664e9SAndroid Build Coastguard Worker   }
Visit(const Styleable * value)95*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(const Styleable* value) {
96*d57664e9SAndroid Build Coastguard Worker     VisitAny(value);
97*d57664e9SAndroid Build Coastguard Worker   }
Visit(const Macro * value)98*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(const Macro* value) {
99*d57664e9SAndroid Build Coastguard Worker     VisitAny(value);
100*d57664e9SAndroid Build Coastguard Worker   }
101*d57664e9SAndroid Build Coastguard Worker };
102*d57664e9SAndroid Build Coastguard Worker 
103*d57664e9SAndroid Build Coastguard Worker // NOLINT, do not add parentheses around T.
104*d57664e9SAndroid Build Coastguard Worker #define DECL_VISIT_COMPOUND_VALUE(T)                   \
105*d57664e9SAndroid Build Coastguard Worker   virtual void Visit(T* value) override { /* NOLINT */ \
106*d57664e9SAndroid Build Coastguard Worker     VisitSubValues(value);                             \
107*d57664e9SAndroid Build Coastguard Worker   }
108*d57664e9SAndroid Build Coastguard Worker 
109*d57664e9SAndroid Build Coastguard Worker // Visits values, and if they are compound values, descends into their components as well.
110*d57664e9SAndroid Build Coastguard Worker struct DescendingValueVisitor : public ValueVisitor {
111*d57664e9SAndroid Build Coastguard Worker   // The compiler will think we're hiding an overload, when we actually intend
112*d57664e9SAndroid Build Coastguard Worker   // to call into RawValueVisitor. This will expose the visit methods in the
113*d57664e9SAndroid Build Coastguard Worker   // super class so the compiler knows we are trying to call them.
114*d57664e9SAndroid Build Coastguard Worker   using ValueVisitor::Visit;
115*d57664e9SAndroid Build Coastguard Worker 
VisitSubValuesDescendingValueVisitor116*d57664e9SAndroid Build Coastguard Worker   void VisitSubValues(Attribute* attribute) {
117*d57664e9SAndroid Build Coastguard Worker     for (Attribute::Symbol& symbol : attribute->symbols) {
118*d57664e9SAndroid Build Coastguard Worker       Visit(&symbol.symbol);
119*d57664e9SAndroid Build Coastguard Worker     }
120*d57664e9SAndroid Build Coastguard Worker   }
121*d57664e9SAndroid Build Coastguard Worker 
VisitSubValuesDescendingValueVisitor122*d57664e9SAndroid Build Coastguard Worker   void VisitSubValues(Style* style) {
123*d57664e9SAndroid Build Coastguard Worker     if (style->parent) {
124*d57664e9SAndroid Build Coastguard Worker       Visit(&style->parent.value());
125*d57664e9SAndroid Build Coastguard Worker     }
126*d57664e9SAndroid Build Coastguard Worker 
127*d57664e9SAndroid Build Coastguard Worker     for (Style::Entry& entry : style->entries) {
128*d57664e9SAndroid Build Coastguard Worker       Visit(&entry.key);
129*d57664e9SAndroid Build Coastguard Worker       entry.value->Accept(this);
130*d57664e9SAndroid Build Coastguard Worker     }
131*d57664e9SAndroid Build Coastguard Worker   }
132*d57664e9SAndroid Build Coastguard Worker 
VisitSubValuesDescendingValueVisitor133*d57664e9SAndroid Build Coastguard Worker   void VisitSubValues(Array* array) {
134*d57664e9SAndroid Build Coastguard Worker     for (std::unique_ptr<Item>& item : array->elements) {
135*d57664e9SAndroid Build Coastguard Worker       item->Accept(this);
136*d57664e9SAndroid Build Coastguard Worker     }
137*d57664e9SAndroid Build Coastguard Worker   }
138*d57664e9SAndroid Build Coastguard Worker 
VisitSubValuesDescendingValueVisitor139*d57664e9SAndroid Build Coastguard Worker   void VisitSubValues(Plural* plural) {
140*d57664e9SAndroid Build Coastguard Worker     for (std::unique_ptr<Item>& item : plural->values) {
141*d57664e9SAndroid Build Coastguard Worker       if (item) {
142*d57664e9SAndroid Build Coastguard Worker         item->Accept(this);
143*d57664e9SAndroid Build Coastguard Worker       }
144*d57664e9SAndroid Build Coastguard Worker     }
145*d57664e9SAndroid Build Coastguard Worker   }
146*d57664e9SAndroid Build Coastguard Worker 
VisitSubValuesDescendingValueVisitor147*d57664e9SAndroid Build Coastguard Worker   void VisitSubValues(Styleable* styleable) {
148*d57664e9SAndroid Build Coastguard Worker     for (Reference& reference : styleable->entries) {
149*d57664e9SAndroid Build Coastguard Worker       Visit(&reference);
150*d57664e9SAndroid Build Coastguard Worker     }
151*d57664e9SAndroid Build Coastguard Worker   }
152*d57664e9SAndroid Build Coastguard Worker 
153*d57664e9SAndroid Build Coastguard Worker   DECL_VISIT_COMPOUND_VALUE(Attribute);
154*d57664e9SAndroid Build Coastguard Worker   DECL_VISIT_COMPOUND_VALUE(Style);
155*d57664e9SAndroid Build Coastguard Worker   DECL_VISIT_COMPOUND_VALUE(Array);
156*d57664e9SAndroid Build Coastguard Worker   DECL_VISIT_COMPOUND_VALUE(Plural);
157*d57664e9SAndroid Build Coastguard Worker   DECL_VISIT_COMPOUND_VALUE(Styleable);
158*d57664e9SAndroid Build Coastguard Worker };
159*d57664e9SAndroid Build Coastguard Worker 
160*d57664e9SAndroid Build Coastguard Worker // Do not use directly. Helper struct for dyn_cast.
161*d57664e9SAndroid Build Coastguard Worker template <typename T>
162*d57664e9SAndroid Build Coastguard Worker struct DynCastVisitor : public ConstValueVisitor {
163*d57664e9SAndroid Build Coastguard Worker   const T* value = nullptr;
164*d57664e9SAndroid Build Coastguard Worker 
VisitDynCastVisitor165*d57664e9SAndroid Build Coastguard Worker   void Visit(const T* v) override {
166*d57664e9SAndroid Build Coastguard Worker     value = v;
167*d57664e9SAndroid Build Coastguard Worker   }
168*d57664e9SAndroid Build Coastguard Worker };
169*d57664e9SAndroid Build Coastguard Worker 
170*d57664e9SAndroid Build Coastguard Worker // Specialization that checks if the value is an Item.
171*d57664e9SAndroid Build Coastguard Worker template <>
172*d57664e9SAndroid Build Coastguard Worker struct DynCastVisitor<Item> : public ConstValueVisitor {
173*d57664e9SAndroid Build Coastguard Worker   const Item* value = nullptr;
174*d57664e9SAndroid Build Coastguard Worker 
175*d57664e9SAndroid Build Coastguard Worker   void VisitItem(const Item* item) override {
176*d57664e9SAndroid Build Coastguard Worker     value = item;
177*d57664e9SAndroid Build Coastguard Worker   }
178*d57664e9SAndroid Build Coastguard Worker };
179*d57664e9SAndroid Build Coastguard Worker 
180*d57664e9SAndroid Build Coastguard Worker // Returns a valid pointer to T if the value is an instance of T. Returns nullptr if value is
181*d57664e9SAndroid Build Coastguard Worker // nullptr of if value is not an instance of T.
182*d57664e9SAndroid Build Coastguard Worker template <typename T>
183*d57664e9SAndroid Build Coastguard Worker const T* ValueCast(const Value* value) {
184*d57664e9SAndroid Build Coastguard Worker   if (!value) {
185*d57664e9SAndroid Build Coastguard Worker     return nullptr;
186*d57664e9SAndroid Build Coastguard Worker   }
187*d57664e9SAndroid Build Coastguard Worker   DynCastVisitor<T> visitor;
188*d57664e9SAndroid Build Coastguard Worker   value->Accept(&visitor);
189*d57664e9SAndroid Build Coastguard Worker   return visitor.value;
190*d57664e9SAndroid Build Coastguard Worker }
191*d57664e9SAndroid Build Coastguard Worker 
192*d57664e9SAndroid Build Coastguard Worker // Non-const version of ValueCast.
193*d57664e9SAndroid Build Coastguard Worker template <typename T>
194*d57664e9SAndroid Build Coastguard Worker T* ValueCast(Value* value) {
195*d57664e9SAndroid Build Coastguard Worker   return const_cast<T*>(ValueCast<T>(static_cast<const Value*>(value)));
196*d57664e9SAndroid Build Coastguard Worker }
197*d57664e9SAndroid Build Coastguard Worker 
198*d57664e9SAndroid Build Coastguard Worker inline void VisitAllValuesInPackage(ResourceTablePackage* pkg, ValueVisitor* visitor) {
199*d57664e9SAndroid Build Coastguard Worker   for (auto& type : pkg->types) {
200*d57664e9SAndroid Build Coastguard Worker     for (auto& entry : type->entries) {
201*d57664e9SAndroid Build Coastguard Worker       for (auto& config_value : entry->values) {
202*d57664e9SAndroid Build Coastguard Worker         config_value->value->Accept(visitor);
203*d57664e9SAndroid Build Coastguard Worker       }
204*d57664e9SAndroid Build Coastguard Worker     }
205*d57664e9SAndroid Build Coastguard Worker   }
206*d57664e9SAndroid Build Coastguard Worker }
207*d57664e9SAndroid Build Coastguard Worker 
208*d57664e9SAndroid Build Coastguard Worker inline void VisitAllValuesInTable(ResourceTable* table, ValueVisitor* visitor) {
209*d57664e9SAndroid Build Coastguard Worker   for (auto& pkg : table->packages) {
210*d57664e9SAndroid Build Coastguard Worker     VisitAllValuesInPackage(pkg.get(), visitor);
211*d57664e9SAndroid Build Coastguard Worker   }
212*d57664e9SAndroid Build Coastguard Worker }
213*d57664e9SAndroid Build Coastguard Worker 
214*d57664e9SAndroid Build Coastguard Worker }  // namespace aapt
215*d57664e9SAndroid Build Coastguard Worker 
216*d57664e9SAndroid Build Coastguard Worker #endif  // AAPT_VALUE_VISITOR_H
217