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 "ResourceValues.h" 21 #include "ResourceTable.h" 22 23 namespace aapt { 24 25 /** 26 * Visits a value and invokes the appropriate method based on its type. Does not traverse 27 * into compound types. Use ValueVisitor for that. 28 */ 29 struct RawValueVisitor { 30 virtual ~RawValueVisitor() = default; 31 visitItemRawValueVisitor32 virtual void visitItem(Item* value) {} visitRawValueVisitor33 virtual void visit(Reference* value) { visitItem(value); } visitRawValueVisitor34 virtual void visit(RawString* value) { visitItem(value); } visitRawValueVisitor35 virtual void visit(String* value) { visitItem(value); } visitRawValueVisitor36 virtual void visit(StyledString* value) { visitItem(value); } visitRawValueVisitor37 virtual void visit(FileReference* value) { visitItem(value); } visitRawValueVisitor38 virtual void visit(Id* value) { visitItem(value); } visitRawValueVisitor39 virtual void visit(BinaryPrimitive* value) { visitItem(value); } 40 visitRawValueVisitor41 virtual void visit(Attribute* value) {} visitRawValueVisitor42 virtual void visit(Style* value) {} visitRawValueVisitor43 virtual void visit(Array* value) {} visitRawValueVisitor44 virtual void visit(Plural* value) {} visitRawValueVisitor45 virtual void visit(Styleable* value) {} 46 }; 47 48 #define DECL_VISIT_COMPOUND_VALUE(T) \ 49 virtual void visit(T* value) { \ 50 visitSubValues(value); \ 51 } 52 53 /** 54 * Visits values, and if they are compound values, visits the components as well. 55 */ 56 struct ValueVisitor : public RawValueVisitor { 57 // The compiler will think we're hiding an overload, when we actually intend 58 // to call into RawValueVisitor. This will expose the visit methods in the super 59 // class so the compiler knows we are trying to call them. 60 using RawValueVisitor::visit; 61 visitSubValuesValueVisitor62 void visitSubValues(Attribute* attribute) { 63 for (Attribute::Symbol& symbol : attribute->symbols) { 64 visit(&symbol.symbol); 65 } 66 } 67 visitSubValuesValueVisitor68 void visitSubValues(Style* style) { 69 if (style->parent) { 70 visit(&style->parent.value()); 71 } 72 73 for (Style::Entry& entry : style->entries) { 74 visit(&entry.key); 75 entry.value->accept(this); 76 } 77 } 78 visitSubValuesValueVisitor79 void visitSubValues(Array* array) { 80 for (std::unique_ptr<Item>& item : array->items) { 81 item->accept(this); 82 } 83 } 84 visitSubValuesValueVisitor85 void visitSubValues(Plural* plural) { 86 for (std::unique_ptr<Item>& item : plural->values) { 87 if (item) { 88 item->accept(this); 89 } 90 } 91 } 92 visitSubValuesValueVisitor93 void visitSubValues(Styleable* styleable) { 94 for (Reference& reference : styleable->entries) { 95 visit(&reference); 96 } 97 } 98 99 DECL_VISIT_COMPOUND_VALUE(Attribute); 100 DECL_VISIT_COMPOUND_VALUE(Style); 101 DECL_VISIT_COMPOUND_VALUE(Array); 102 DECL_VISIT_COMPOUND_VALUE(Plural); 103 DECL_VISIT_COMPOUND_VALUE(Styleable); 104 }; 105 106 /** 107 * Do not use directly. Helper struct for dyn_cast. 108 */ 109 template <typename T> 110 struct DynCastVisitor : public RawValueVisitor { 111 T* value = nullptr; 112 visitDynCastVisitor113 void visit(T* v) override { 114 value = v; 115 } 116 }; 117 118 /** 119 * Specialization that checks if the value is an Item. 120 */ 121 template <> 122 struct DynCastVisitor<Item> : public RawValueVisitor { 123 Item* value = nullptr; 124 125 void visitItem(Item* item) override { 126 value = item; 127 } 128 }; 129 130 template <typename T> 131 const T* valueCast(const Value* value) { 132 return valueCast<T>(const_cast<Value*>(value)); 133 } 134 135 /** 136 * Returns a valid pointer to T if the Value is of subtype T. 137 * Otherwise, returns nullptr. 138 */ 139 template <typename T> 140 T* valueCast(Value* value) { 141 if (!value) { 142 return nullptr; 143 } 144 DynCastVisitor<T> visitor; 145 value->accept(&visitor); 146 return visitor.value; 147 } 148 149 inline void visitAllValuesInPackage(ResourceTablePackage* pkg, RawValueVisitor* visitor) { 150 for (auto& type : pkg->types) { 151 for (auto& entry : type->entries) { 152 for (auto& configValue : entry->values) { 153 configValue->value->accept(visitor); 154 } 155 } 156 } 157 } 158 159 inline void visitAllValuesInTable(ResourceTable* table, RawValueVisitor* visitor) { 160 for (auto& pkg : table->packages) { 161 visitAllValuesInPackage(pkg.get(), visitor); 162 } 163 } 164 165 } // namespace aapt 166 167 #endif // AAPT_VALUE_VISITOR_H 168