| /* |
| * 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 "ResourceValues.h" |
| #include "ResourceTable.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. |
| */ |
| struct RawValueVisitor { |
| virtual ~RawValueVisitor() = default; |
| |
| virtual void visitItem(Item* 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) {} |
| virtual void visit(Style* value) {} |
| virtual void visit(Array* value) {} |
| virtual void visit(Plural* value) {} |
| virtual void visit(Styleable* value) {} |
| }; |
| |
| #define DECL_VISIT_COMPOUND_VALUE(T) \ |
| virtual void visit(T* value) { \ |
| visitSubValues(value); \ |
| } |
| |
| /** |
| * Visits values, and if they are compound values, visits the components as well. |
| */ |
| struct ValueVisitor : public RawValueVisitor { |
| // 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 RawValueVisitor::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->items) { |
| 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 RawValueVisitor { |
| T* value = nullptr; |
| |
| void visit(T* v) override { |
| value = v; |
| } |
| }; |
| |
| /** |
| * Specialization that checks if the value is an Item. |
| */ |
| template <> |
| struct DynCastVisitor<Item> : public RawValueVisitor { |
| Item* value = nullptr; |
| |
| void visitItem(Item* item) override { |
| value = item; |
| } |
| }; |
| |
| /** |
| * Returns a valid pointer to T if the Value is of subtype T. |
| * Otherwise, returns nullptr. |
| */ |
| template <typename T> |
| T* valueCast(Value* value) { |
| if (!value) { |
| return nullptr; |
| } |
| DynCastVisitor<T> visitor; |
| value->accept(&visitor); |
| return visitor.value; |
| } |
| |
| |
| inline void visitAllValuesInPackage(ResourceTablePackage* pkg, RawValueVisitor* visitor) { |
| for (auto& type : pkg->types) { |
| for (auto& entry : type->entries) { |
| for (auto& configValue : entry->values) { |
| configValue->value->accept(visitor); |
| } |
| } |
| } |
| } |
| |
| inline void visitAllValuesInTable(ResourceTable* table, RawValueVisitor* visitor) { |
| for (auto& pkg : table->packages) { |
| visitAllValuesInPackage(pkg.get(), visitor); |
| } |
| } |
| |
| } // namespace aapt |
| |
| #endif // AAPT_VALUE_VISITOR_H |