diff options
Diffstat (limited to 'tools/aapt2/xml/XmlDom.h')
-rw-r--r-- | tools/aapt2/xml/XmlDom.h | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/tools/aapt2/xml/XmlDom.h b/tools/aapt2/xml/XmlDom.h new file mode 100644 index 000000000000..033b0a4d031c --- /dev/null +++ b/tools/aapt2/xml/XmlDom.h @@ -0,0 +1,220 @@ +/* + * 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_XML_DOM_H +#define AAPT_XML_DOM_H + +#include "Diagnostics.h" +#include "Resource.h" +#include "ResourceValues.h" +#include "util/StringPiece.h" +#include "util/Util.h" +#include "xml/XmlUtil.h" + +#include <istream> +#include <memory> +#include <string> +#include <vector> + +namespace aapt { +namespace xml { + +struct RawVisitor; + +/** + * Base class for all XML nodes. + */ +struct Node { + Node* parent = nullptr; + size_t lineNumber = 0; + size_t columnNumber = 0; + std::u16string comment; + std::vector<std::unique_ptr<Node>> children; + + virtual ~Node() = default; + + void addChild(std::unique_ptr<Node> child); + virtual void accept(RawVisitor* visitor) = 0; +}; + +/** + * Base class that implements the visitor methods for a + * subclass of Node. + */ +template <typename Derived> +struct BaseNode : public Node { + virtual void accept(RawVisitor* visitor) override; +}; + +/** + * A Namespace XML node. Can only have one child. + */ +struct Namespace : public BaseNode<Namespace> { + std::u16string namespacePrefix; + std::u16string namespaceUri; +}; + +struct AaptAttribute { + ResourceId id; + aapt::Attribute attribute; +}; + +/** + * An XML attribute. + */ +struct Attribute { + std::u16string namespaceUri; + std::u16string name; + std::u16string value; + + Maybe<AaptAttribute> compiledAttribute; + std::unique_ptr<Item> compiledValue; +}; + +/** + * An Element XML node. + */ +struct Element : public BaseNode<Element> { + std::u16string namespaceUri; + std::u16string name; + std::vector<Attribute> attributes; + + Attribute* findAttribute(const StringPiece16& ns, const StringPiece16& name); + xml::Element* findChild(const StringPiece16& ns, const StringPiece16& name); + xml::Element* findChildWithAttribute(const StringPiece16& ns, const StringPiece16& name, + const StringPiece16& attrNs, + const StringPiece16& attrName, + const StringPiece16& attrValue); + std::vector<xml::Element*> getChildElements(); +}; + +/** + * A Text (CDATA) XML node. Can not have any children. + */ +struct Text : public BaseNode<Text> { + std::u16string text; +}; + +/** + * An XML resource with a source, name, and XML tree. + */ +struct XmlResource { + ResourceFile file; + std::unique_ptr<xml::Node> root; +}; + +/** + * Inflates an XML DOM from a text stream, logging errors to the logger. + * Returns the root node on success, or nullptr on failure. + */ +std::unique_ptr<XmlResource> inflate(std::istream* in, IDiagnostics* diag, const Source& source); + +/** + * Inflates an XML DOM from a binary ResXMLTree, logging errors to the logger. + * Returns the root node on success, or nullptr on failure. + */ +std::unique_ptr<XmlResource> inflate(const void* data, size_t dataLen, IDiagnostics* diag, + const Source& source); + +Element* findRootElement(XmlResource* doc); +Element* findRootElement(Node* node); + +/** + * A visitor interface for the different XML Node subtypes. This will not traverse into + * children. Use Visitor for that. + */ +struct RawVisitor { + virtual ~RawVisitor() = default; + + virtual void visit(Namespace* node) {} + virtual void visit(Element* node) {} + virtual void visit(Text* text) {} +}; + +/** + * Visitor whose default implementation visits the children nodes of any node. + */ +struct Visitor : public RawVisitor { + using RawVisitor::visit; + + void visit(Namespace* node) override { + visitChildren(node); + } + + void visit(Element* node) override { + visitChildren(node); + } + + void visit(Text* text) override { + visitChildren(text); + } + + void visitChildren(Node* node) { + for (auto& child : node->children) { + child->accept(this); + } + } +}; + +/** + * An XML DOM visitor that will record the package name for a namespace prefix. + */ +class PackageAwareVisitor : public Visitor, public IPackageDeclStack { +private: + struct PackageDecl { + std::u16string prefix; + ExtractedPackage package; + }; + + std::vector<PackageDecl> mPackageDecls; + +public: + using Visitor::visit; + + void visit(Namespace* ns) override; + Maybe<ExtractedPackage> transformPackageAlias( + const StringPiece16& alias, const StringPiece16& localPackage) const override; +}; + +// Implementations + +template <typename Derived> +void BaseNode<Derived>::accept(RawVisitor* visitor) { + visitor->visit(static_cast<Derived*>(this)); +} + +template <typename T> +struct NodeCastImpl : public RawVisitor { + using RawVisitor::visit; + + T* value = nullptr; + + void visit(T* v) override { + value = v; + } +}; + +template <typename T> +T* nodeCast(Node* node) { + NodeCastImpl<T> visitor; + node->accept(&visitor); + return visitor.value; +} + +} // namespace xml +} // namespace aapt + +#endif // AAPT_XML_DOM_H |