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