Home | History | Annotate | Download | only in aapt2
      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 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