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