diff options
author | Adam Lesinski <adamlesinski@google.com> | 2015-08-14 14:26:04 -0700 |
---|---|---|
committer | Adam Lesinski <adamlesinski@google.com> | 2015-10-16 12:13:08 -0700 |
commit | 1ab598f46c3ff520a67f9d80194847741f3467ab (patch) | |
tree | 4846790211599fdd7a9bb35ec94df4a6ec4839d6 /tools/aapt2/ValueVisitor.h | |
parent | 547c346bb34878b691fd53e54aa3a88efcc5dc6f (diff) |
AAPT2: Separate out the various steps
An early refactor. Some ideas became clearer as
development continued. Now the various phases are much
clearer and more easily reusable.
Also added a ton of tests!
Change-Id: Ic8f0a70c8222370352e63533b329c40457c0903e
Diffstat (limited to 'tools/aapt2/ValueVisitor.h')
-rw-r--r-- | tools/aapt2/ValueVisitor.h | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/tools/aapt2/ValueVisitor.h b/tools/aapt2/ValueVisitor.h new file mode 100644 index 000000000000..ee058aa1a37b --- /dev/null +++ b/tools/aapt2/ValueVisitor.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AAPT_VALUE_VISITOR_H +#define AAPT_VALUE_VISITOR_H + +#include "ResourceValues.h" + +namespace aapt { + +/** + * Visits a value and invokes the appropriate method based on its type. Does not traverse + * into compound types. Use ValueVisitor for that. + */ +struct RawValueVisitor { + virtual ~RawValueVisitor() = default; + + virtual void visitItem(Item* value) {} + virtual void visit(Reference* value) { visitItem(value); } + virtual void visit(RawString* value) { visitItem(value); } + virtual void visit(String* value) { visitItem(value); } + virtual void visit(StyledString* value) { visitItem(value); } + virtual void visit(FileReference* value) { visitItem(value); } + virtual void visit(Id* value) { visitItem(value); } + virtual void visit(BinaryPrimitive* value) { visitItem(value); } + + virtual void visit(Attribute* value) {} + virtual void visit(Style* value) {} + virtual void visit(Array* value) {} + virtual void visit(Plural* value) {} + virtual void visit(Styleable* value) {} +}; + +#define DECL_VISIT_COMPOUND_VALUE(T) \ + virtual void visit(T* value) { \ + visitSubValues(value); \ + } + +/** + * Visits values, and if they are compound values, visits the components as well. + */ +struct ValueVisitor : public RawValueVisitor { + // The compiler will think we're hiding an overload, when we actually intend + // to call into RawValueVisitor. This will expose the visit methods in the super + // class so the compiler knows we are trying to call them. + using RawValueVisitor::visit; + + void visitSubValues(Attribute* attribute) { + for (Attribute::Symbol& symbol : attribute->symbols) { + visit(&symbol.symbol); + } + } + + void visitSubValues(Style* style) { + if (style->parent) { + visit(&style->parent.value()); + } + + for (Style::Entry& entry : style->entries) { + visit(&entry.key); + entry.value->accept(this); + } + } + + void visitSubValues(Array* array) { + for (std::unique_ptr<Item>& item : array->items) { + item->accept(this); + } + } + + void visitSubValues(Plural* plural) { + for (std::unique_ptr<Item>& item : plural->values) { + if (item) { + item->accept(this); + } + } + } + + void visitSubValues(Styleable* styleable) { + for (Reference& reference : styleable->entries) { + visit(&reference); + } + } + + DECL_VISIT_COMPOUND_VALUE(Attribute); + DECL_VISIT_COMPOUND_VALUE(Style); + DECL_VISIT_COMPOUND_VALUE(Array); + DECL_VISIT_COMPOUND_VALUE(Plural); + DECL_VISIT_COMPOUND_VALUE(Styleable); +}; + +/** + * Do not use directly. Helper struct for dyn_cast. + */ +template <typename T> +struct DynCastVisitor : public RawValueVisitor { + T* value = nullptr; + + void visit(T* v) override { + value = v; + } +}; + +/** + * Returns a valid pointer to T if the Value is of subtype T. + * Otherwise, returns nullptr. + */ +template <typename T> +T* valueCast(Value* value) { + if (!value) { + return nullptr; + } + DynCastVisitor<T> visitor; + value->accept(&visitor); + return visitor.value; +} + +} // namespace aapt + +#endif // AAPT_VALUE_VISITOR_H |