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 32 virtual void VisitAny(Value* value) {} 33 virtual void VisitItem(Item* value) { VisitAny(value); } 34 virtual void Visit(Reference* value) { VisitItem(value); } 35 virtual void Visit(RawString* value) { VisitItem(value); } 36 virtual void Visit(String* value) { VisitItem(value); } 37 virtual void Visit(StyledString* value) { VisitItem(value); } 38 virtual void Visit(FileReference* value) { VisitItem(value); } 39 virtual void Visit(Id* value) { VisitItem(value); } 40 virtual void Visit(BinaryPrimitive* value) { VisitItem(value); } 41 42 virtual void Visit(Attribute* value) { VisitAny(value); } 43 virtual void Visit(Style* value) { VisitAny(value); } 44 virtual void Visit(Array* value) { VisitAny(value); } 45 virtual void Visit(Plural* value) { VisitAny(value); } 46 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 65 void VisitSubValues(Attribute* attribute) { 66 for (Attribute::Symbol& symbol : attribute->symbols) { 67 Visit(&symbol.symbol); 68 } 69 } 70 71 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 82 void VisitSubValues(Array* array) { 83 for (std::unique_ptr<Item>& item : array->items) { 84 item->Accept(this); 85 } 86 } 87 88 void VisitSubValues(Plural* plural) { 89 for (std::unique_ptr<Item>& item : plural->values) { 90 if (item) { 91 item->Accept(this); 92 } 93 } 94 } 95 96 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 116 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