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 "ResourceTable.h"
     21 #include "ResourceValues.h"
     22 
     23 namespace aapt {
     24 
     25 /**
     26  * Visits a value and invokes the appropriate method based on its type. Does not
     27  * traverse into compound types. Use ValueVisitor for that.
     28  */
     29 struct RawValueVisitor {
     30   virtual ~RawValueVisitor() = default;
     31 
     32   virtual void VisitAny(Value* value) {}
     33   virtual void VisitItem(Item* value) { VisitAny(value); }
     34   virtual void Visit(Reference* value) { VisitItem(value); }
     35   virtual void Visit(RawString* value) { VisitItem(value); }
     36   virtual void Visit(String* value) { VisitItem(value); }
     37   virtual void Visit(StyledString* value) { VisitItem(value); }
     38   virtual void Visit(FileReference* value) { VisitItem(value); }
     39   virtual void Visit(Id* value) { VisitItem(value); }
     40   virtual void Visit(BinaryPrimitive* value) { VisitItem(value); }
     41 
     42   virtual void Visit(Attribute* value) { VisitAny(value); }
     43   virtual void Visit(Style* value) { VisitAny(value); }
     44   virtual void Visit(Array* value) { VisitAny(value); }
     45   virtual void Visit(Plural* value) { VisitAny(value); }
     46   virtual void Visit(Styleable* value) { VisitAny(value); }
     47 };
     48 
     49 // NOLINT, do not add parentheses around T.
     50 #define DECL_VISIT_COMPOUND_VALUE(T)                   \
     51   virtual void Visit(T* value) override { /* NOLINT */ \
     52     VisitSubValues(value);                             \
     53   }
     54 
     55 /**
     56  * Visits values, and if they are compound values, visits the components as
     57  * well.
     58  */
     59 struct ValueVisitor : public RawValueVisitor {
     60   // The compiler will think we're hiding an overload, when we actually intend
     61   // to call into RawValueVisitor. This will expose the visit methods in the
     62   // super class so the compiler knows we are trying to call them.
     63   using RawValueVisitor::Visit;
     64 
     65   void VisitSubValues(Attribute* attribute) {
     66     for (Attribute::Symbol& symbol : attribute->symbols) {
     67       Visit(&symbol.symbol);
     68     }
     69   }
     70 
     71   void VisitSubValues(Style* style) {
     72     if (style->parent) {
     73       Visit(&style->parent.value());
     74     }
     75 
     76     for (Style::Entry& entry : style->entries) {
     77       Visit(&entry.key);
     78       entry.value->Accept(this);
     79     }
     80   }
     81 
     82   void VisitSubValues(Array* array) {
     83     for (std::unique_ptr<Item>& item : array->elements) {
     84       item->Accept(this);
     85     }
     86   }
     87 
     88   void VisitSubValues(Plural* plural) {
     89     for (std::unique_ptr<Item>& item : plural->values) {
     90       if (item) {
     91         item->Accept(this);
     92       }
     93     }
     94   }
     95 
     96   void VisitSubValues(Styleable* styleable) {
     97     for (Reference& reference : styleable->entries) {
     98       Visit(&reference);
     99     }
    100   }
    101 
    102   DECL_VISIT_COMPOUND_VALUE(Attribute);
    103   DECL_VISIT_COMPOUND_VALUE(Style);
    104   DECL_VISIT_COMPOUND_VALUE(Array);
    105   DECL_VISIT_COMPOUND_VALUE(Plural);
    106   DECL_VISIT_COMPOUND_VALUE(Styleable);
    107 };
    108 
    109 /**
    110  * Do not use directly. Helper struct for dyn_cast.
    111  */
    112 template <typename T>
    113 struct DynCastVisitor : public RawValueVisitor {
    114   T* value = nullptr;
    115 
    116   void Visit(T* v) override { value = v; }
    117 };
    118 
    119 /**
    120  * Specialization that checks if the value is an Item.
    121  */
    122 template <>
    123 struct DynCastVisitor<Item> : public RawValueVisitor {
    124   Item* value = nullptr;
    125 
    126   void VisitItem(Item* item) override { value = item; }
    127 };
    128 
    129 template <typename T>
    130 const T* ValueCast(const Value* value) {
    131   return ValueCast<T>(const_cast<Value*>(value));
    132 }
    133 
    134 /**
    135  * Returns a valid pointer to T if the Value is of subtype T.
    136  * Otherwise, returns nullptr.
    137  */
    138 template <typename T>
    139 T* ValueCast(Value* value) {
    140   if (!value) {
    141     return nullptr;
    142   }
    143   DynCastVisitor<T> visitor;
    144   value->Accept(&visitor);
    145   return visitor.value;
    146 }
    147 
    148 inline void VisitAllValuesInPackage(ResourceTablePackage* pkg,
    149                                     RawValueVisitor* visitor) {
    150   for (auto& type : pkg->types) {
    151     for (auto& entry : type->entries) {
    152       for (auto& config_value : entry->values) {
    153         config_value->value->Accept(visitor);
    154       }
    155     }
    156   }
    157 }
    158 
    159 inline void VisitAllValuesInTable(ResourceTable* table,
    160                                   RawValueVisitor* visitor) {
    161   for (auto& pkg : table->packages) {
    162     VisitAllValuesInPackage(pkg.get(), visitor);
    163   }
    164 }
    165 
    166 }  // namespace aapt
    167 
    168 #endif  // AAPT_VALUE_VISITOR_H
    169