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