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