1*d57664e9SAndroid Build Coastguard Worker /* 2*d57664e9SAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project 3*d57664e9SAndroid Build Coastguard Worker * 4*d57664e9SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*d57664e9SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*d57664e9SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*d57664e9SAndroid Build Coastguard Worker * 8*d57664e9SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*d57664e9SAndroid Build Coastguard Worker * 10*d57664e9SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*d57664e9SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*d57664e9SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*d57664e9SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*d57664e9SAndroid Build Coastguard Worker * limitations under the License. 15*d57664e9SAndroid Build Coastguard Worker */ 16*d57664e9SAndroid Build Coastguard Worker 17*d57664e9SAndroid Build Coastguard Worker #ifndef AAPT_VALUE_VISITOR_H 18*d57664e9SAndroid Build Coastguard Worker #define AAPT_VALUE_VISITOR_H 19*d57664e9SAndroid Build Coastguard Worker 20*d57664e9SAndroid Build Coastguard Worker #include "ResourceTable.h" 21*d57664e9SAndroid Build Coastguard Worker #include "ResourceValues.h" 22*d57664e9SAndroid Build Coastguard Worker 23*d57664e9SAndroid Build Coastguard Worker namespace aapt { 24*d57664e9SAndroid Build Coastguard Worker 25*d57664e9SAndroid Build Coastguard Worker // Visits a value and invokes the appropriate method based on its type. 26*d57664e9SAndroid Build Coastguard Worker // Does not traverse into compound types. Use ValueVisitor for that. 27*d57664e9SAndroid Build Coastguard Worker class ValueVisitor { 28*d57664e9SAndroid Build Coastguard Worker public: 29*d57664e9SAndroid Build Coastguard Worker virtual ~ValueVisitor() = default; 30*d57664e9SAndroid Build Coastguard Worker VisitAny(Value * value)31*d57664e9SAndroid Build Coastguard Worker virtual void VisitAny(Value* value) {} VisitItem(Item * value)32*d57664e9SAndroid Build Coastguard Worker virtual void VisitItem(Item* value) { VisitAny(value); } Visit(Reference * value)33*d57664e9SAndroid Build Coastguard Worker virtual void Visit(Reference* value) { VisitItem(value); } Visit(RawString * value)34*d57664e9SAndroid Build Coastguard Worker virtual void Visit(RawString* value) { VisitItem(value); } Visit(String * value)35*d57664e9SAndroid Build Coastguard Worker virtual void Visit(String* value) { VisitItem(value); } Visit(StyledString * value)36*d57664e9SAndroid Build Coastguard Worker virtual void Visit(StyledString* value) { VisitItem(value); } Visit(FileReference * value)37*d57664e9SAndroid Build Coastguard Worker virtual void Visit(FileReference* value) { VisitItem(value); } Visit(Id * value)38*d57664e9SAndroid Build Coastguard Worker virtual void Visit(Id* value) { VisitItem(value); } Visit(BinaryPrimitive * value)39*d57664e9SAndroid Build Coastguard Worker virtual void Visit(BinaryPrimitive* value) { VisitItem(value); } 40*d57664e9SAndroid Build Coastguard Worker Visit(Attribute * value)41*d57664e9SAndroid Build Coastguard Worker virtual void Visit(Attribute* value) { VisitAny(value); } Visit(Style * value)42*d57664e9SAndroid Build Coastguard Worker virtual void Visit(Style* value) { VisitAny(value); } Visit(Array * value)43*d57664e9SAndroid Build Coastguard Worker virtual void Visit(Array* value) { VisitAny(value); } Visit(Plural * value)44*d57664e9SAndroid Build Coastguard Worker virtual void Visit(Plural* value) { VisitAny(value); } Visit(Styleable * value)45*d57664e9SAndroid Build Coastguard Worker virtual void Visit(Styleable* value) { VisitAny(value); } Visit(Macro * value)46*d57664e9SAndroid Build Coastguard Worker virtual void Visit(Macro* value) { 47*d57664e9SAndroid Build Coastguard Worker VisitAny(value); 48*d57664e9SAndroid Build Coastguard Worker } 49*d57664e9SAndroid Build Coastguard Worker }; 50*d57664e9SAndroid Build Coastguard Worker 51*d57664e9SAndroid Build Coastguard Worker // Const version of ValueVisitor. 52*d57664e9SAndroid Build Coastguard Worker class ConstValueVisitor { 53*d57664e9SAndroid Build Coastguard Worker public: 54*d57664e9SAndroid Build Coastguard Worker virtual ~ConstValueVisitor() = default; 55*d57664e9SAndroid Build Coastguard Worker VisitAny(const Value * value)56*d57664e9SAndroid Build Coastguard Worker virtual void VisitAny(const Value* value) { 57*d57664e9SAndroid Build Coastguard Worker } VisitItem(const Item * value)58*d57664e9SAndroid Build Coastguard Worker virtual void VisitItem(const Item* value) { 59*d57664e9SAndroid Build Coastguard Worker VisitAny(value); 60*d57664e9SAndroid Build Coastguard Worker } Visit(const Reference * value)61*d57664e9SAndroid Build Coastguard Worker virtual void Visit(const Reference* value) { 62*d57664e9SAndroid Build Coastguard Worker VisitItem(value); 63*d57664e9SAndroid Build Coastguard Worker } Visit(const RawString * value)64*d57664e9SAndroid Build Coastguard Worker virtual void Visit(const RawString* value) { 65*d57664e9SAndroid Build Coastguard Worker VisitItem(value); 66*d57664e9SAndroid Build Coastguard Worker } Visit(const String * value)67*d57664e9SAndroid Build Coastguard Worker virtual void Visit(const String* value) { 68*d57664e9SAndroid Build Coastguard Worker VisitItem(value); 69*d57664e9SAndroid Build Coastguard Worker } Visit(const StyledString * value)70*d57664e9SAndroid Build Coastguard Worker virtual void Visit(const StyledString* value) { 71*d57664e9SAndroid Build Coastguard Worker VisitItem(value); 72*d57664e9SAndroid Build Coastguard Worker } Visit(const FileReference * value)73*d57664e9SAndroid Build Coastguard Worker virtual void Visit(const FileReference* value) { 74*d57664e9SAndroid Build Coastguard Worker VisitItem(value); 75*d57664e9SAndroid Build Coastguard Worker } Visit(const Id * value)76*d57664e9SAndroid Build Coastguard Worker virtual void Visit(const Id* value) { 77*d57664e9SAndroid Build Coastguard Worker VisitItem(value); 78*d57664e9SAndroid Build Coastguard Worker } Visit(const BinaryPrimitive * value)79*d57664e9SAndroid Build Coastguard Worker virtual void Visit(const BinaryPrimitive* value) { 80*d57664e9SAndroid Build Coastguard Worker VisitItem(value); 81*d57664e9SAndroid Build Coastguard Worker } 82*d57664e9SAndroid Build Coastguard Worker Visit(const Attribute * value)83*d57664e9SAndroid Build Coastguard Worker virtual void Visit(const Attribute* value) { 84*d57664e9SAndroid Build Coastguard Worker VisitAny(value); 85*d57664e9SAndroid Build Coastguard Worker } Visit(const Style * value)86*d57664e9SAndroid Build Coastguard Worker virtual void Visit(const Style* value) { 87*d57664e9SAndroid Build Coastguard Worker VisitAny(value); 88*d57664e9SAndroid Build Coastguard Worker } Visit(const Array * value)89*d57664e9SAndroid Build Coastguard Worker virtual void Visit(const Array* value) { 90*d57664e9SAndroid Build Coastguard Worker VisitAny(value); 91*d57664e9SAndroid Build Coastguard Worker } Visit(const Plural * value)92*d57664e9SAndroid Build Coastguard Worker virtual void Visit(const Plural* value) { 93*d57664e9SAndroid Build Coastguard Worker VisitAny(value); 94*d57664e9SAndroid Build Coastguard Worker } Visit(const Styleable * value)95*d57664e9SAndroid Build Coastguard Worker virtual void Visit(const Styleable* value) { 96*d57664e9SAndroid Build Coastguard Worker VisitAny(value); 97*d57664e9SAndroid Build Coastguard Worker } Visit(const Macro * value)98*d57664e9SAndroid Build Coastguard Worker virtual void Visit(const Macro* value) { 99*d57664e9SAndroid Build Coastguard Worker VisitAny(value); 100*d57664e9SAndroid Build Coastguard Worker } 101*d57664e9SAndroid Build Coastguard Worker }; 102*d57664e9SAndroid Build Coastguard Worker 103*d57664e9SAndroid Build Coastguard Worker // NOLINT, do not add parentheses around T. 104*d57664e9SAndroid Build Coastguard Worker #define DECL_VISIT_COMPOUND_VALUE(T) \ 105*d57664e9SAndroid Build Coastguard Worker virtual void Visit(T* value) override { /* NOLINT */ \ 106*d57664e9SAndroid Build Coastguard Worker VisitSubValues(value); \ 107*d57664e9SAndroid Build Coastguard Worker } 108*d57664e9SAndroid Build Coastguard Worker 109*d57664e9SAndroid Build Coastguard Worker // Visits values, and if they are compound values, descends into their components as well. 110*d57664e9SAndroid Build Coastguard Worker struct DescendingValueVisitor : public ValueVisitor { 111*d57664e9SAndroid Build Coastguard Worker // The compiler will think we're hiding an overload, when we actually intend 112*d57664e9SAndroid Build Coastguard Worker // to call into RawValueVisitor. This will expose the visit methods in the 113*d57664e9SAndroid Build Coastguard Worker // super class so the compiler knows we are trying to call them. 114*d57664e9SAndroid Build Coastguard Worker using ValueVisitor::Visit; 115*d57664e9SAndroid Build Coastguard Worker VisitSubValuesDescendingValueVisitor116*d57664e9SAndroid Build Coastguard Worker void VisitSubValues(Attribute* attribute) { 117*d57664e9SAndroid Build Coastguard Worker for (Attribute::Symbol& symbol : attribute->symbols) { 118*d57664e9SAndroid Build Coastguard Worker Visit(&symbol.symbol); 119*d57664e9SAndroid Build Coastguard Worker } 120*d57664e9SAndroid Build Coastguard Worker } 121*d57664e9SAndroid Build Coastguard Worker VisitSubValuesDescendingValueVisitor122*d57664e9SAndroid Build Coastguard Worker void VisitSubValues(Style* style) { 123*d57664e9SAndroid Build Coastguard Worker if (style->parent) { 124*d57664e9SAndroid Build Coastguard Worker Visit(&style->parent.value()); 125*d57664e9SAndroid Build Coastguard Worker } 126*d57664e9SAndroid Build Coastguard Worker 127*d57664e9SAndroid Build Coastguard Worker for (Style::Entry& entry : style->entries) { 128*d57664e9SAndroid Build Coastguard Worker Visit(&entry.key); 129*d57664e9SAndroid Build Coastguard Worker entry.value->Accept(this); 130*d57664e9SAndroid Build Coastguard Worker } 131*d57664e9SAndroid Build Coastguard Worker } 132*d57664e9SAndroid Build Coastguard Worker VisitSubValuesDescendingValueVisitor133*d57664e9SAndroid Build Coastguard Worker void VisitSubValues(Array* array) { 134*d57664e9SAndroid Build Coastguard Worker for (std::unique_ptr<Item>& item : array->elements) { 135*d57664e9SAndroid Build Coastguard Worker item->Accept(this); 136*d57664e9SAndroid Build Coastguard Worker } 137*d57664e9SAndroid Build Coastguard Worker } 138*d57664e9SAndroid Build Coastguard Worker VisitSubValuesDescendingValueVisitor139*d57664e9SAndroid Build Coastguard Worker void VisitSubValues(Plural* plural) { 140*d57664e9SAndroid Build Coastguard Worker for (std::unique_ptr<Item>& item : plural->values) { 141*d57664e9SAndroid Build Coastguard Worker if (item) { 142*d57664e9SAndroid Build Coastguard Worker item->Accept(this); 143*d57664e9SAndroid Build Coastguard Worker } 144*d57664e9SAndroid Build Coastguard Worker } 145*d57664e9SAndroid Build Coastguard Worker } 146*d57664e9SAndroid Build Coastguard Worker VisitSubValuesDescendingValueVisitor147*d57664e9SAndroid Build Coastguard Worker void VisitSubValues(Styleable* styleable) { 148*d57664e9SAndroid Build Coastguard Worker for (Reference& reference : styleable->entries) { 149*d57664e9SAndroid Build Coastguard Worker Visit(&reference); 150*d57664e9SAndroid Build Coastguard Worker } 151*d57664e9SAndroid Build Coastguard Worker } 152*d57664e9SAndroid Build Coastguard Worker 153*d57664e9SAndroid Build Coastguard Worker DECL_VISIT_COMPOUND_VALUE(Attribute); 154*d57664e9SAndroid Build Coastguard Worker DECL_VISIT_COMPOUND_VALUE(Style); 155*d57664e9SAndroid Build Coastguard Worker DECL_VISIT_COMPOUND_VALUE(Array); 156*d57664e9SAndroid Build Coastguard Worker DECL_VISIT_COMPOUND_VALUE(Plural); 157*d57664e9SAndroid Build Coastguard Worker DECL_VISIT_COMPOUND_VALUE(Styleable); 158*d57664e9SAndroid Build Coastguard Worker }; 159*d57664e9SAndroid Build Coastguard Worker 160*d57664e9SAndroid Build Coastguard Worker // Do not use directly. Helper struct for dyn_cast. 161*d57664e9SAndroid Build Coastguard Worker template <typename T> 162*d57664e9SAndroid Build Coastguard Worker struct DynCastVisitor : public ConstValueVisitor { 163*d57664e9SAndroid Build Coastguard Worker const T* value = nullptr; 164*d57664e9SAndroid Build Coastguard Worker VisitDynCastVisitor165*d57664e9SAndroid Build Coastguard Worker void Visit(const T* v) override { 166*d57664e9SAndroid Build Coastguard Worker value = v; 167*d57664e9SAndroid Build Coastguard Worker } 168*d57664e9SAndroid Build Coastguard Worker }; 169*d57664e9SAndroid Build Coastguard Worker 170*d57664e9SAndroid Build Coastguard Worker // Specialization that checks if the value is an Item. 171*d57664e9SAndroid Build Coastguard Worker template <> 172*d57664e9SAndroid Build Coastguard Worker struct DynCastVisitor<Item> : public ConstValueVisitor { 173*d57664e9SAndroid Build Coastguard Worker const Item* value = nullptr; 174*d57664e9SAndroid Build Coastguard Worker 175*d57664e9SAndroid Build Coastguard Worker void VisitItem(const Item* item) override { 176*d57664e9SAndroid Build Coastguard Worker value = item; 177*d57664e9SAndroid Build Coastguard Worker } 178*d57664e9SAndroid Build Coastguard Worker }; 179*d57664e9SAndroid Build Coastguard Worker 180*d57664e9SAndroid Build Coastguard Worker // Returns a valid pointer to T if the value is an instance of T. Returns nullptr if value is 181*d57664e9SAndroid Build Coastguard Worker // nullptr of if value is not an instance of T. 182*d57664e9SAndroid Build Coastguard Worker template <typename T> 183*d57664e9SAndroid Build Coastguard Worker const T* ValueCast(const Value* value) { 184*d57664e9SAndroid Build Coastguard Worker if (!value) { 185*d57664e9SAndroid Build Coastguard Worker return nullptr; 186*d57664e9SAndroid Build Coastguard Worker } 187*d57664e9SAndroid Build Coastguard Worker DynCastVisitor<T> visitor; 188*d57664e9SAndroid Build Coastguard Worker value->Accept(&visitor); 189*d57664e9SAndroid Build Coastguard Worker return visitor.value; 190*d57664e9SAndroid Build Coastguard Worker } 191*d57664e9SAndroid Build Coastguard Worker 192*d57664e9SAndroid Build Coastguard Worker // Non-const version of ValueCast. 193*d57664e9SAndroid Build Coastguard Worker template <typename T> 194*d57664e9SAndroid Build Coastguard Worker T* ValueCast(Value* value) { 195*d57664e9SAndroid Build Coastguard Worker return const_cast<T*>(ValueCast<T>(static_cast<const Value*>(value))); 196*d57664e9SAndroid Build Coastguard Worker } 197*d57664e9SAndroid Build Coastguard Worker 198*d57664e9SAndroid Build Coastguard Worker inline void VisitAllValuesInPackage(ResourceTablePackage* pkg, ValueVisitor* visitor) { 199*d57664e9SAndroid Build Coastguard Worker for (auto& type : pkg->types) { 200*d57664e9SAndroid Build Coastguard Worker for (auto& entry : type->entries) { 201*d57664e9SAndroid Build Coastguard Worker for (auto& config_value : entry->values) { 202*d57664e9SAndroid Build Coastguard Worker config_value->value->Accept(visitor); 203*d57664e9SAndroid Build Coastguard Worker } 204*d57664e9SAndroid Build Coastguard Worker } 205*d57664e9SAndroid Build Coastguard Worker } 206*d57664e9SAndroid Build Coastguard Worker } 207*d57664e9SAndroid Build Coastguard Worker 208*d57664e9SAndroid Build Coastguard Worker inline void VisitAllValuesInTable(ResourceTable* table, ValueVisitor* visitor) { 209*d57664e9SAndroid Build Coastguard Worker for (auto& pkg : table->packages) { 210*d57664e9SAndroid Build Coastguard Worker VisitAllValuesInPackage(pkg.get(), visitor); 211*d57664e9SAndroid Build Coastguard Worker } 212*d57664e9SAndroid Build Coastguard Worker } 213*d57664e9SAndroid Build Coastguard Worker 214*d57664e9SAndroid Build Coastguard Worker } // namespace aapt 215*d57664e9SAndroid Build Coastguard Worker 216*d57664e9SAndroid Build Coastguard Worker #endif // AAPT_VALUE_VISITOR_H 217