11ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/*
21ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Copyright (C) 2015 The Android Open Source Project
31ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *
41ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
51ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * you may not use this file except in compliance with the License.
61ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * You may obtain a copy of the License at
71ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *
81ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
91ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski *
101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Unless required by applicable law or agreed to in writing, software
111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * See the License for the specific language governing permissions and
141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * limitations under the License.
151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */
161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#ifndef AAPT_VALUE_VISITOR_H
181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#define AAPT_VALUE_VISITOR_H
191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "ResourceTable.h"
21cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski#include "ResourceValues.h"
221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskinamespace aapt {
241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/**
26cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Visits a value and invokes the appropriate method based on its type. Does not
27ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski * traverse into compound types. Use ValueVisitor for that.
281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */
291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistruct RawValueVisitor {
30cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  virtual ~RawValueVisitor() = default;
31cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
32ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  virtual void VisitAny(Value* value) {}
33ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  virtual void VisitItem(Item* value) { VisitAny(value); }
34ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  virtual void Visit(Reference* value) { VisitItem(value); }
35ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  virtual void Visit(RawString* value) { VisitItem(value); }
36ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  virtual void Visit(String* value) { VisitItem(value); }
37ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  virtual void Visit(StyledString* value) { VisitItem(value); }
38ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  virtual void Visit(FileReference* value) { VisitItem(value); }
39ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  virtual void Visit(Id* value) { VisitItem(value); }
40ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  virtual void Visit(BinaryPrimitive* value) { VisitItem(value); }
41ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
42ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  virtual void Visit(Attribute* value) { VisitAny(value); }
43ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  virtual void Visit(Style* value) { VisitAny(value); }
44ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  virtual void Visit(Array* value) { VisitAny(value); }
45ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  virtual void Visit(Plural* value) { VisitAny(value); }
46ceb9b2f80f853059233cdd29057f39a5960a74aeAdam Lesinski  virtual void Visit(Styleable* value) { VisitAny(value); }
471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
49470f8fcb5c0c59b28b5f73ee011a797b05085da7Chih-Hung Hsieh// NOLINT, do not add parentheses around T.
50ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#define DECL_VISIT_COMPOUND_VALUE(T)                   \
51ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  virtual void Visit(T* value) override { /* NOLINT */ \
52ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    VisitSubValues(value);                             \
53cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/**
56cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * Visits values, and if they are compound values, visits the components as
57cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski * well.
581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */
591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistruct ValueVisitor : public RawValueVisitor {
60cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // The compiler will think we're hiding an overload, when we actually intend
61cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  // to call into RawValueVisitor. This will expose the visit methods in the
62ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  // super class so the compiler knows we are trying to call them.
63ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  using RawValueVisitor::Visit;
64cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
65ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  void VisitSubValues(Attribute* attribute) {
66cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    for (Attribute::Symbol& symbol : attribute->symbols) {
67ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      Visit(&symbol.symbol);
681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
69cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
701ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
71ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  void VisitSubValues(Style* style) {
72cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (style->parent) {
73ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      Visit(&style->parent.value());
74cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
751ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
76cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    for (Style::Entry& entry : style->entries) {
77ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      Visit(&entry.key);
78ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      entry.value->Accept(this);
791ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
80cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
811ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
82ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  void VisitSubValues(Array* array) {
83cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    for (std::unique_ptr<Item>& item : array->items) {
84ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      item->Accept(this);
851ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
86cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
871ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
88ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  void VisitSubValues(Plural* plural) {
89cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    for (std::unique_ptr<Item>& item : plural->values) {
90cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (item) {
91ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        item->Accept(this);
92cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
931ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
94cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
951ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
96ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  void VisitSubValues(Styleable* styleable) {
97cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    for (Reference& reference : styleable->entries) {
98ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      Visit(&reference);
991ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
100cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
1011ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
102cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  DECL_VISIT_COMPOUND_VALUE(Attribute);
103cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  DECL_VISIT_COMPOUND_VALUE(Style);
104cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  DECL_VISIT_COMPOUND_VALUE(Array);
105cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  DECL_VISIT_COMPOUND_VALUE(Plural);
106cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  DECL_VISIT_COMPOUND_VALUE(Styleable);
1071ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
1081ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1091ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/**
1101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Do not use directly. Helper struct for dyn_cast.
1111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */
1121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskitemplate <typename T>
1131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskistruct DynCastVisitor : public RawValueVisitor {
114cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  T* value = nullptr;
1151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
116ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  void Visit(T* v) override { value = v; }
1171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski};
1181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski/**
120e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski * Specialization that checks if the value is an Item.
121e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski */
122e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinskitemplate <>
123e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinskistruct DynCastVisitor<Item> : public RawValueVisitor {
124cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  Item* value = nullptr;
125e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski
126ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  void VisitItem(Item* item) override { value = item; }
127e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski};
128e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski
129458b877488c12ea4336d8fc00a95d9c0298bd6d0Adam Lesinskitemplate <typename T>
130ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiconst T* ValueCast(const Value* value) {
131ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  return ValueCast<T>(const_cast<Value*>(value));
132458b877488c12ea4336d8fc00a95d9c0298bd6d0Adam Lesinski}
133458b877488c12ea4336d8fc00a95d9c0298bd6d0Adam Lesinski
134e78fd617ec60139a973a01925fa7adad31febb39Adam Lesinski/**
1351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Returns a valid pointer to T if the Value is of subtype T.
1361ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski * Otherwise, returns nullptr.
1371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski */
1381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskitemplate <typename T>
139ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam LesinskiT* ValueCast(Value* value) {
140cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (!value) {
141cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return nullptr;
142cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
143cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  DynCastVisitor<T> visitor;
144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  value->Accept(&visitor);
145cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return visitor.value;
1461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}
1471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
148ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiinline void VisitAllValuesInPackage(ResourceTablePackage* pkg,
149cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                                    RawValueVisitor* visitor) {
150cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  for (auto& type : pkg->types) {
151cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    for (auto& entry : type->entries) {
152ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      for (auto& config_value : entry->values) {
153ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        config_value->value->Accept(visitor);
154cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
15559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    }
156cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
15759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski}
15859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
159ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiinline void VisitAllValuesInTable(ResourceTable* table,
160cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                                  RawValueVisitor* visitor) {
161cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  for (auto& pkg : table->packages) {
162ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    VisitAllValuesInPackage(pkg.get(), visitor);
163cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
16459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski}
16559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
166cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski}  // namespace aapt
1671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
168cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski#endif  // AAPT_VALUE_VISITOR_H
169