AAPT2
First checking of AAPT2. The individual phases of AAPT2 work, but there
are some missing pieces.
For early testing we are missing:
- Need to properly mark file references and include them in package
- Need to package into zip
Final AAPT for apps we are missing:
- Need to crush PNGs
- Need to parse 9-patches
- Need to validate all of AndroidManifest.xml
- Need to write align method to align resource tables for splits.
Final AAPT for apps + system we are missing:
- Need to handle overlays
- Need to store comments for R file
- Need to handle --shared-lib (dynamic references too).
New AAPT features coming:
- Need to import compiled libraries
- Name mangling
- R file generation for library code
Change-Id: I95f8a63581b81a1f424ae6fb2c373c883b72c18d
diff --git a/tools/aapt2/XmlPullParser.h b/tools/aapt2/XmlPullParser.h
new file mode 100644
index 0000000..c667df2
--- /dev/null
+++ b/tools/aapt2/XmlPullParser.h
@@ -0,0 +1,234 @@
+/*
+ * 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_PULL_PARSER_H
+#define AAPT_XML_PULL_PARSER_H
+
+#include <algorithm>
+#include <ostream>
+#include <string>
+#include <vector>
+
+#include "StringPiece.h"
+
+namespace aapt {
+
+class XmlPullParser {
+public:
+ enum class Event {
+ kBadDocument,
+ kStartDocument,
+ kEndDocument,
+
+ kStartNamespace,
+ kEndNamespace,
+ kStartElement,
+ kEndElement,
+ kText,
+ kComment,
+ };
+
+ static void skipCurrentElement(XmlPullParser* parser);
+ static bool isGoodEvent(Event event);
+
+ virtual ~XmlPullParser() {}
+
+ /**
+ * Returns the current event that is being processed.
+ */
+ virtual Event getEvent() const = 0;
+
+ virtual const std::string& getLastError() const = 0;
+
+ /**
+ * Note, unlike XmlPullParser, the first call to next() will return
+ * StartElement of the first element.
+ */
+ virtual Event next() = 0;
+
+ //
+ // These are available for all nodes.
+ //
+
+ virtual const std::u16string& getComment() const = 0;
+ virtual size_t getLineNumber() const = 0;
+ virtual size_t getDepth() const = 0;
+
+ /**
+ * Returns the character data for a Text event.
+ */
+ virtual const std::u16string& getText() const = 0;
+
+ /**
+ * Namespace prefix is available for StartNamespace and EndNamespace.
+ */
+ virtual const std::u16string& getNamespacePrefix() const = 0;
+
+ /**
+ * Namespace URI is available for StartNamespace.
+ */
+ virtual const std::u16string& getNamespaceUri() const = 0;
+
+ //
+ // These are available for StartElement and EndElement.
+ //
+
+ virtual const std::u16string& getElementNamespace() const = 0;
+ virtual const std::u16string& getElementName() const = 0;
+
+ //
+ // Remaining methods are for retrieving information about attributes
+ // associated with a StartElement.
+ //
+ // Attributes must be in sorted order (according to the less than operator
+ // of struct Attribute).
+ //
+
+ struct Attribute {
+ std::u16string namespaceUri;
+ std::u16string name;
+ std::u16string value;
+
+ int compare(const Attribute& rhs) const;
+ bool operator<(const Attribute& rhs) const;
+ bool operator==(const Attribute& rhs) const;
+ bool operator!=(const Attribute& rhs) const;
+ };
+
+ using const_iterator = std::vector<Attribute>::const_iterator;
+
+ virtual const_iterator beginAttributes() const = 0;
+ virtual const_iterator endAttributes() const = 0;
+ virtual size_t getAttributeCount() const = 0;
+ const_iterator findAttribute(StringPiece16 namespaceUri, StringPiece16 name) const;
+};
+
+/*
+ * Automatically reads up to the end tag of the element it was initialized with
+ * when being destroyed.
+ */
+class AutoFinishElement {
+public:
+ AutoFinishElement(const std::shared_ptr<XmlPullParser>& parser);
+ ~AutoFinishElement();
+
+private:
+ std::shared_ptr<XmlPullParser> mParser;
+ int mDepth;
+};
+
+//
+// Implementation
+//
+
+inline ::std::ostream& operator<<(::std::ostream& out, XmlPullParser::Event event) {
+ switch (event) {
+ case XmlPullParser::Event::kBadDocument: return out << "BadDocument";
+ case XmlPullParser::Event::kStartDocument: return out << "StartDocument";
+ case XmlPullParser::Event::kEndDocument: return out << "EndDocument";
+ case XmlPullParser::Event::kStartNamespace: return out << "StartNamespace";
+ case XmlPullParser::Event::kEndNamespace: return out << "EndNamespace";
+ case XmlPullParser::Event::kStartElement: return out << "StartElement";
+ case XmlPullParser::Event::kEndElement: return out << "EndElement";
+ case XmlPullParser::Event::kText: return out << "Text";
+ case XmlPullParser::Event::kComment: return out << "Comment";
+ }
+ return out;
+}
+
+inline void XmlPullParser::skipCurrentElement(XmlPullParser* parser) {
+ int depth = 1;
+ while (depth > 0) {
+ switch (parser->next()) {
+ case Event::kEndDocument:
+ case Event::kBadDocument:
+ return;
+ case Event::kStartElement:
+ depth++;
+ break;
+ case Event::kEndElement:
+ depth--;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+inline bool XmlPullParser::isGoodEvent(XmlPullParser::Event event) {
+ return event != Event::kBadDocument && event != Event::kEndDocument;
+}
+
+inline int XmlPullParser::Attribute::compare(const Attribute& rhs) const {
+ int cmp = namespaceUri.compare(rhs.namespaceUri);
+ if (cmp != 0) return cmp;
+ return name.compare(rhs.name);
+}
+
+inline bool XmlPullParser::Attribute::operator<(const Attribute& rhs) const {
+ return compare(rhs) < 0;
+}
+
+inline bool XmlPullParser::Attribute::operator==(const Attribute& rhs) const {
+ return compare(rhs) == 0;
+}
+
+inline bool XmlPullParser::Attribute::operator!=(const Attribute& rhs) const {
+ return compare(rhs) != 0;
+}
+
+inline XmlPullParser::const_iterator XmlPullParser::findAttribute(StringPiece16 namespaceUri,
+ StringPiece16 name) const {
+ const auto endIter = endAttributes();
+ const auto iter = std::lower_bound(beginAttributes(), endIter,
+ std::pair<StringPiece16, StringPiece16>(namespaceUri, name),
+ [](const Attribute& attr, const std::pair<StringPiece16, StringPiece16>& rhs) -> bool {
+ int cmp = attr.namespaceUri.compare(0, attr.namespaceUri.size(),
+ rhs.first.data(), rhs.first.size());
+ if (cmp < 0) return true;
+ if (cmp > 0) return false;
+ cmp = attr.name.compare(0, attr.name.size(), rhs.second.data(), rhs.second.size());
+ if (cmp < 0) return true;
+ return false;
+ }
+ );
+
+ if (iter != endIter && namespaceUri == iter->namespaceUri && name == iter->name) {
+ return iter;
+ }
+ return endIter;
+}
+
+inline AutoFinishElement::AutoFinishElement(const std::shared_ptr<XmlPullParser>& parser) :
+ mParser(parser), mDepth(parser->getDepth()) {
+}
+
+inline AutoFinishElement::~AutoFinishElement() {
+ int depth;
+ XmlPullParser::Event event;
+ while ((depth = mParser->getDepth()) >= mDepth &&
+ XmlPullParser::isGoodEvent(event = mParser->getEvent())) {
+ if (depth == mDepth && (event == XmlPullParser::Event::kEndElement ||
+ event == XmlPullParser::Event::kEndNamespace)) {
+ return;
+ }
+ mParser->next();
+ }
+}
+
+} // namespace aapt
+
+#endif // AAPT_XML_PULL_PARSER_H