/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef AAPT_VALUE_VISITOR_H #define AAPT_VALUE_VISITOR_H #include "ResourceTable.h" #include "ResourceValues.h" namespace aapt { // Visits a value and invokes the appropriate method based on its type. // Does not traverse into compound types. Use ValueVisitor for that. class ValueVisitor { public: virtual ~ValueVisitor() = default; virtual void VisitAny(Value* value) {} virtual void VisitItem(Item* value) { VisitAny(value); } virtual void Visit(Reference* value) { VisitItem(value); } virtual void Visit(RawString* value) { VisitItem(value); } virtual void Visit(String* value) { VisitItem(value); } virtual void Visit(StyledString* value) { VisitItem(value); } virtual void Visit(FileReference* value) { VisitItem(value); } virtual void Visit(Id* value) { VisitItem(value); } virtual void Visit(BinaryPrimitive* value) { VisitItem(value); } virtual void Visit(Attribute* value) { VisitAny(value); } virtual void Visit(Style* value) { VisitAny(value); } virtual void Visit(Array* value) { VisitAny(value); } virtual void Visit(Plural* value) { VisitAny(value); } virtual void Visit(Styleable* value) { VisitAny(value); } }; // Const version of ValueVisitor. class ConstValueVisitor { public: virtual ~ConstValueVisitor() = default; virtual void VisitAny(const Value* value) { } virtual void VisitItem(const Item* value) { VisitAny(value); } virtual void Visit(const Reference* value) { VisitItem(value); } virtual void Visit(const RawString* value) { VisitItem(value); } virtual void Visit(const String* value) { VisitItem(value); } virtual void Visit(const StyledString* value) { VisitItem(value); } virtual void Visit(const FileReference* value) { VisitItem(value); } virtual void Visit(const Id* value) { VisitItem(value); } virtual void Visit(const BinaryPrimitive* value) { VisitItem(value); } virtual void Visit(const Attribute* value) { VisitAny(value); } virtual void Visit(const Style* value) { VisitAny(value); } virtual void Visit(const Array* value) { VisitAny(value); } virtual void Visit(const Plural* value) { VisitAny(value); } virtual void Visit(const Styleable* value) { VisitAny(value); } }; // NOLINT, do not add parentheses around T. #define DECL_VISIT_COMPOUND_VALUE(T) \ virtual void Visit(T* value) override { /* NOLINT */ \ VisitSubValues(value); \ } // Visits values, and if they are compound values, descends into their components as well. struct DescendingValueVisitor : public ValueVisitor { // The compiler will think we're hiding an overload, when we actually intend // to call into RawValueVisitor. This will expose the visit methods in the // super class so the compiler knows we are trying to call them. using ValueVisitor::Visit; void VisitSubValues(Attribute* attribute) { for (Attribute::Symbol& symbol : attribute->symbols) { Visit(&symbol.symbol); } } void VisitSubValues(Style* style) { if (style->parent) { Visit(&style->parent.value()); } for (Style::Entry& entry : style->entries) { Visit(&entry.key); entry.value->Accept(this); } } void VisitSubValues(Array* array) { for (std::unique_ptr<Item>& item : array->elements) { item->Accept(this); } } void VisitSubValues(Plural* plural) { for (std::unique_ptr<Item>& item : plural->values) { if (item) { item->Accept(this); } } } void VisitSubValues(Styleable* styleable) { for (Reference& reference : styleable->entries) { Visit(&reference); } } DECL_VISIT_COMPOUND_VALUE(Attribute); DECL_VISIT_COMPOUND_VALUE(Style); DECL_VISIT_COMPOUND_VALUE(Array); DECL_VISIT_COMPOUND_VALUE(Plural); DECL_VISIT_COMPOUND_VALUE(Styleable); }; // Do not use directly. Helper struct for dyn_cast. template <typename T> struct DynCastVisitor : public ConstValueVisitor { const T* value = nullptr; void Visit(const T* v) override { value = v; } }; // Specialization that checks if the value is an Item. template <> struct DynCastVisitor<Item> : public ConstValueVisitor { const Item* value = nullptr; void VisitItem(const Item* item) override { value = item; } }; // Returns a valid pointer to T if the value is an instance of T. Returns nullptr if value is // nullptr of if value is not an instance of T. template <typename T> const T* ValueCast(const Value* value) { if (!value) { return nullptr; } DynCastVisitor<T> visitor; value->Accept(&visitor); return visitor.value; } // Non-const version of ValueCast. template <typename T> T* ValueCast(Value* value) { return const_cast<T*>(ValueCast<T>(static_cast<const Value*>(value))); } inline void VisitAllValuesInPackage(ResourceTablePackage* pkg, ValueVisitor* visitor) { for (auto& type : pkg->types) { for (auto& entry : type->entries) { for (auto& config_value : entry->values) { config_value->value->Accept(visitor); } } } } inline void VisitAllValuesInTable(ResourceTable* table, ValueVisitor* visitor) { for (auto& pkg : table->packages) { VisitAllValuesInPackage(pkg.get(), visitor); } } } // namespace aapt #endif // AAPT_VALUE_VISITOR_H