• 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 "ResourceTable.h"
21 #include "ResourceValues.h"
22 
23 namespace aapt {
24 
25 /**
26  * Visits a value and invokes the appropriate method based on its type. Does not
27  * traverse into compound types. Use ValueVisitor for that.
28  */
29 struct RawValueVisitor {
30   virtual ~RawValueVisitor() = default;
31 
VisitAnyRawValueVisitor32   virtual void VisitAny(Value* value) {}
VisitItemRawValueVisitor33   virtual void VisitItem(Item* value) { VisitAny(value); }
VisitRawValueVisitor34   virtual void Visit(Reference* value) { VisitItem(value); }
VisitRawValueVisitor35   virtual void Visit(RawString* value) { VisitItem(value); }
VisitRawValueVisitor36   virtual void Visit(String* value) { VisitItem(value); }
VisitRawValueVisitor37   virtual void Visit(StyledString* value) { VisitItem(value); }
VisitRawValueVisitor38   virtual void Visit(FileReference* value) { VisitItem(value); }
VisitRawValueVisitor39   virtual void Visit(Id* value) { VisitItem(value); }
VisitRawValueVisitor40   virtual void Visit(BinaryPrimitive* value) { VisitItem(value); }
41 
VisitRawValueVisitor42   virtual void Visit(Attribute* value) { VisitAny(value); }
VisitRawValueVisitor43   virtual void Visit(Style* value) { VisitAny(value); }
VisitRawValueVisitor44   virtual void Visit(Array* value) { VisitAny(value); }
VisitRawValueVisitor45   virtual void Visit(Plural* value) { VisitAny(value); }
VisitRawValueVisitor46   virtual void Visit(Styleable* value) { VisitAny(value); }
47 };
48 
49 // NOLINT, do not add parentheses around T.
50 #define DECL_VISIT_COMPOUND_VALUE(T)                   \
51   virtual void Visit(T* value) override { /* NOLINT */ \
52     VisitSubValues(value);                             \
53   }
54 
55 /**
56  * Visits values, and if they are compound values, visits the components as
57  * well.
58  */
59 struct ValueVisitor : public RawValueVisitor {
60   // The compiler will think we're hiding an overload, when we actually intend
61   // to call into RawValueVisitor. This will expose the visit methods in the
62   // super class so the compiler knows we are trying to call them.
63   using RawValueVisitor::Visit;
64 
VisitSubValuesValueVisitor65   void VisitSubValues(Attribute* attribute) {
66     for (Attribute::Symbol& symbol : attribute->symbols) {
67       Visit(&symbol.symbol);
68     }
69   }
70 
VisitSubValuesValueVisitor71   void VisitSubValues(Style* style) {
72     if (style->parent) {
73       Visit(&style->parent.value());
74     }
75 
76     for (Style::Entry& entry : style->entries) {
77       Visit(&entry.key);
78       entry.value->Accept(this);
79     }
80   }
81 
VisitSubValuesValueVisitor82   void VisitSubValues(Array* array) {
83     for (std::unique_ptr<Item>& item : array->elements) {
84       item->Accept(this);
85     }
86   }
87 
VisitSubValuesValueVisitor88   void VisitSubValues(Plural* plural) {
89     for (std::unique_ptr<Item>& item : plural->values) {
90       if (item) {
91         item->Accept(this);
92       }
93     }
94   }
95 
VisitSubValuesValueVisitor96   void VisitSubValues(Styleable* styleable) {
97     for (Reference& reference : styleable->entries) {
98       Visit(&reference);
99     }
100   }
101 
102   DECL_VISIT_COMPOUND_VALUE(Attribute);
103   DECL_VISIT_COMPOUND_VALUE(Style);
104   DECL_VISIT_COMPOUND_VALUE(Array);
105   DECL_VISIT_COMPOUND_VALUE(Plural);
106   DECL_VISIT_COMPOUND_VALUE(Styleable);
107 };
108 
109 /**
110  * Do not use directly. Helper struct for dyn_cast.
111  */
112 template <typename T>
113 struct DynCastVisitor : public RawValueVisitor {
114   T* value = nullptr;
115 
VisitDynCastVisitor116   void Visit(T* v) override { value = v; }
117 };
118 
119 /**
120  * Specialization that checks if the value is an Item.
121  */
122 template <>
123 struct DynCastVisitor<Item> : public RawValueVisitor {
124   Item* value = nullptr;
125 
126   void VisitItem(Item* item) override { value = item; }
127 };
128 
129 template <typename T>
130 const T* ValueCast(const Value* value) {
131   return ValueCast<T>(const_cast<Value*>(value));
132 }
133 
134 /**
135  * Returns a valid pointer to T if the Value is of subtype T.
136  * Otherwise, returns nullptr.
137  */
138 template <typename T>
139 T* ValueCast(Value* value) {
140   if (!value) {
141     return nullptr;
142   }
143   DynCastVisitor<T> visitor;
144   value->Accept(&visitor);
145   return visitor.value;
146 }
147 
148 inline void VisitAllValuesInPackage(ResourceTablePackage* pkg,
149                                     RawValueVisitor* visitor) {
150   for (auto& type : pkg->types) {
151     for (auto& entry : type->entries) {
152       for (auto& config_value : entry->values) {
153         config_value->value->Accept(visitor);
154       }
155     }
156   }
157 }
158 
159 inline void VisitAllValuesInTable(ResourceTable* table,
160                                   RawValueVisitor* visitor) {
161   for (auto& pkg : table->packages) {
162     VisitAllValuesInPackage(pkg.get(), visitor);
163   }
164 }
165 
166 }  // namespace aapt
167 
168 #endif  // AAPT_VALUE_VISITOR_H
169