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