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 32 virtual void visitItem(Item* value) {} 33 virtual void visit(Reference* value) { visitItem(value); } 34 virtual void visit(RawString* value) { visitItem(value); } 35 virtual void visit(String* value) { visitItem(value); } 36 virtual void visit(StyledString* value) { visitItem(value); } 37 virtual void visit(FileReference* value) { visitItem(value); } 38 virtual void visit(Id* value) { visitItem(value); } 39 virtual void visit(BinaryPrimitive* value) { visitItem(value); } 40 41 virtual void visit(Attribute* value) {} 42 virtual void visit(Style* value) {} 43 virtual void visit(Array* value) {} 44 virtual void visit(Plural* value) {} 45 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 62 void visitSubValues(Attribute* attribute) { 63 for (Attribute::Symbol& symbol : attribute->symbols) { 64 visit(&symbol.symbol); 65 } 66 } 67 68 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 79 void visitSubValues(Array* array) { 80 for (std::unique_ptr<Item>& item : array->items) { 81 item->accept(this); 82 } 83 } 84 85 void visitSubValues(Plural* plural) { 86 for (std::unique_ptr<Item>& item : plural->values) { 87 if (item) { 88 item->accept(this); 89 } 90 } 91 } 92 93 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 113 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 /** 131 * Returns a valid pointer to T if the Value is of subtype T. 132 * Otherwise, returns nullptr. 133 */ 134 template <typename T> 135 T* valueCast(Value* value) { 136 if (!value) { 137 return nullptr; 138 } 139 DynCastVisitor<T> visitor; 140 value->accept(&visitor); 141 return visitor.value; 142 } 143 144 145 inline void visitAllValuesInPackage(ResourceTablePackage* pkg, RawValueVisitor* visitor) { 146 for (auto& type : pkg->types) { 147 for (auto& entry : type->entries) { 148 for (auto& configValue : entry->values) { 149 configValue->value->accept(visitor); 150 } 151 } 152 } 153 } 154 155 inline void visitAllValuesInTable(ResourceTable* table, RawValueVisitor* visitor) { 156 for (auto& pkg : table->packages) { 157 visitAllValuesInPackage(pkg.get(), visitor); 158 } 159 } 160 161 } // namespace aapt 162 163 #endif // AAPT_VALUE_VISITOR_H 164