16f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/*
26f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Copyright (C) 2015 The Android Open Source Project
36f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *
46f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
56f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * you may not use this file except in compliance with the License.
66f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * You may obtain a copy of the License at
76f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *
86f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
96f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski *
106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Unless required by applicable law or agreed to in writing, software
116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * See the License for the specific language governing permissions and
146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * limitations under the License.
156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */
166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#ifndef AAPT_XML_PULL_PARSER_H
186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#define AAPT_XML_PULL_PARSER_H
196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "Resource.h"
211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include "process/IResourceTableConsumer.h"
22467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "util/Maybe.h"
23467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "util/StringPiece.h"
24467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski#include "xml/XmlUtil.h"
251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <algorithm>
271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <expat.h>
281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <istream>
296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <ostream>
301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <queue>
311ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski#include <stack>
326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <string>
336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <vector>
346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace aapt {
36467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinskinamespace xml {
376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
381ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiclass XmlPullParser : public IPackageDeclStack {
396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskipublic:
406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    enum class Event {
416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        kBadDocument,
426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        kStartDocument,
436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        kEndDocument,
446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        kStartNamespace,
466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        kEndNamespace,
476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        kStartElement,
486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        kEndElement,
496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        kText,
506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        kComment,
516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    };
526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    /**
541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski     * Skips to the next direct descendant node of the given startDepth,
551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski     * skipping namespace nodes.
561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski     *
571ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski     * When nextChildNode returns true, you can expect Comments, Text, and StartElement events.
581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski     */
591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    static bool nextChildNode(XmlPullParser* parser, size_t startDepth);
601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    static bool skipCurrentElement(XmlPullParser* parser);
616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    static bool isGoodEvent(Event event);
626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    XmlPullParser(std::istream& in);
64467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski    ~XmlPullParser();
656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    /**
676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * Returns the current event that is being processed.
686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     */
691ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    Event getEvent() const;
706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
711ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    const std::string& getLastError() const;
726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    /**
746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * Note, unlike XmlPullParser, the first call to next() will return
756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * StartElement of the first element.
766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     */
771ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    Event next();
786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    //
806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // These are available for all nodes.
816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    //
826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
831ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    const std::u16string& getComment() const;
841ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    size_t getLineNumber() const;
851ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    size_t getDepth() const;
866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    /**
886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     * Returns the character data for a Text event.
896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     */
901ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    const std::u16string& getText() const;
916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
9224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    //
9324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    // Namespace prefix and URI are available for StartNamespace and EndNamespace.
9424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    //
9524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski
961ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    const std::u16string& getNamespacePrefix() const;
971ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    const std::u16string& getNamespaceUri() const;
986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
99467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski    //
100467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski    // These are available for StartElement and EndElement.
101467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski    //
102467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
103467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski    const std::u16string& getElementNamespace() const;
104467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski    const std::u16string& getElementName() const;
105467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
10624aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski    /*
10724aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski     * Uses the current stack of namespaces to resolve the package. Eg:
10824aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski     * xmlns:app = "http://schemas.android.com/apk/res/com.android.app"
10924aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski     * ...
11024aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski     * android:text="@app:string/message"
11124aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski     *
11224aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski     * In this case, 'app' will be converted to 'com.android.app'.
11324aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski     *
11424aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski     * If xmlns:app="http://schemas.android.com/apk/res-auto", then
11524aad163bc88cb10d2275385e9afc3de7f342d65Adam Lesinski     * 'package' will be set to 'defaultPackage'.
1166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski     */
117467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski    Maybe<ExtractedPackage> transformPackageAlias(
118467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski            const StringPiece16& alias, const StringPiece16& localPackage) const override;
1196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    //
1216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // Remaining methods are for retrieving information about attributes
1226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // associated with a StartElement.
1236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    //
1246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // Attributes must be in sorted order (according to the less than operator
1256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    // of struct Attribute).
1266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    //
1276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    struct Attribute {
1296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        std::u16string namespaceUri;
1306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        std::u16string name;
1316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        std::u16string value;
1326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        int compare(const Attribute& rhs) const;
1346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        bool operator<(const Attribute& rhs) const;
1356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        bool operator==(const Attribute& rhs) const;
1366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        bool operator!=(const Attribute& rhs) const;
1376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    };
1386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    using const_iterator = std::vector<Attribute>::const_iterator;
1406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1411ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    const_iterator beginAttributes() const;
1421ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    const_iterator endAttributes() const;
1431ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    size_t getAttributeCount() const;
1446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    const_iterator findAttribute(StringPiece16 namespaceUri, StringPiece16 name) const;
1451ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1461ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiprivate:
1471ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    static void XMLCALL startNamespaceHandler(void* userData, const char* prefix, const char* uri);
1481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    static void XMLCALL startElementHandler(void* userData, const char* name, const char** attrs);
1491ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    static void XMLCALL characterDataHandler(void* userData, const char* s, int len);
1501ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    static void XMLCALL endElementHandler(void* userData, const char* name);
1511ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    static void XMLCALL endNamespaceHandler(void* userData, const char* prefix);
1521ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    static void XMLCALL commentDataHandler(void* userData, const char* comment);
1531ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1541ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    struct EventData {
1551ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        Event event;
1561ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        size_t lineNumber;
1571ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        size_t depth;
1581ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        std::u16string data1;
1591ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        std::u16string data2;
1601ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        std::vector<Attribute> attributes;
1611ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    };
1621ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
1631ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    std::istream& mIn;
1641ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    XML_Parser mParser;
1651ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    char mBuffer[16384];
1661ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    std::queue<EventData> mEventQueue;
1671ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    std::string mLastError;
1681ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    const std::u16string mEmpty;
1691ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    size_t mDepth;
1701ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    std::stack<std::u16string> mNamespaceUris;
171467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
172467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski    struct PackageDecl {
173467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski        std::u16string prefix;
174467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski        ExtractedPackage package;
175467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski    };
176467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski    std::vector<PackageDecl> mPackageAliases;
1776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski};
1786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
179467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski/**
180467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski * Finds the attribute in the current element within the global namespace.
181467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski */
182467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam LesinskiMaybe<StringPiece16> findAttribute(const XmlPullParser* parser, const StringPiece16& name);
183467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
184467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski/**
185467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski * Finds the attribute in the current element within the global namespace. The attribute's value
186467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski * must not be the empty string.
187467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski */
188467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam LesinskiMaybe<StringPiece16> findNonEmptyAttribute(const XmlPullParser* parser, const StringPiece16& name);
189467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski
1906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski//
1916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski// Implementation
1926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski//
1936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
1946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline ::std::ostream& operator<<(::std::ostream& out, XmlPullParser::Event event) {
1956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    switch (event) {
1966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        case XmlPullParser::Event::kBadDocument: return out << "BadDocument";
1976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        case XmlPullParser::Event::kStartDocument: return out << "StartDocument";
1986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        case XmlPullParser::Event::kEndDocument: return out << "EndDocument";
1996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        case XmlPullParser::Event::kStartNamespace: return out << "StartNamespace";
2006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        case XmlPullParser::Event::kEndNamespace: return out << "EndNamespace";
2016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        case XmlPullParser::Event::kStartElement: return out << "StartElement";
2026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        case XmlPullParser::Event::kEndElement: return out << "EndElement";
2036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        case XmlPullParser::Event::kText: return out << "Text";
2046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        case XmlPullParser::Event::kComment: return out << "Comment";
2056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    }
2066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return out;
2076f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2091ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiinline bool XmlPullParser::nextChildNode(XmlPullParser* parser, size_t startDepth) {
2101ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    Event event;
2111ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2121ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    // First get back to the start depth.
2131ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    while (isGoodEvent(event = parser->next()) && parser->getDepth() > startDepth + 1) {}
2141ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2151ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    // Now look for the first good node.
2161ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    while ((event != Event::kEndElement || parser->getDepth() > startDepth) && isGoodEvent(event)) {
2171ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        switch (event) {
2181ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        case Event::kText:
2191ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        case Event::kComment:
2201ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        case Event::kStartElement:
2211ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            return true;
2221ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        default:
2231ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski            break;
2241ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        }
2251ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski        event = parser->next();
2261ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    }
2271ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    return false;
2281ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski}
2291ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski
2301ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinskiinline bool XmlPullParser::skipCurrentElement(XmlPullParser* parser) {
2316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    int depth = 1;
2326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    while (depth > 0) {
2336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        switch (parser->next()) {
2346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            case Event::kEndDocument:
2351ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                return true;
2366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            case Event::kBadDocument:
2371ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski                return false;
2386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            case Event::kStartElement:
2396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski                depth++;
2406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski                break;
2416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            case Event::kEndElement:
2426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski                depth--;
2436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski                break;
2446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            default:
2456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski                break;
2466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        }
2476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    }
2481ab598f46c3ff520a67f9d80194847741f3467abAdam Lesinski    return true;
2496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline bool XmlPullParser::isGoodEvent(XmlPullParser::Event event) {
2526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return event != Event::kBadDocument && event != Event::kEndDocument;
2536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline int XmlPullParser::Attribute::compare(const Attribute& rhs) const {
2566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    int cmp = namespaceUri.compare(rhs.namespaceUri);
2576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    if (cmp != 0) return cmp;
2586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return name.compare(rhs.name);
2596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline bool XmlPullParser::Attribute::operator<(const Attribute& rhs) const {
2626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return compare(rhs) < 0;
2636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline bool XmlPullParser::Attribute::operator==(const Attribute& rhs) const {
2666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return compare(rhs) == 0;
2676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline bool XmlPullParser::Attribute::operator!=(const Attribute& rhs) const {
2706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return compare(rhs) != 0;
2716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline XmlPullParser::const_iterator XmlPullParser::findAttribute(StringPiece16 namespaceUri,
2746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski                                                                  StringPiece16 name) const {
2756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    const auto endIter = endAttributes();
2766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    const auto iter = std::lower_bound(beginAttributes(), endIter,
2776f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            std::pair<StringPiece16, StringPiece16>(namespaceUri, name),
2786f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            [](const Attribute& attr, const std::pair<StringPiece16, StringPiece16>& rhs) -> bool {
2796f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski                int cmp = attr.namespaceUri.compare(0, attr.namespaceUri.size(),
2806f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski                        rhs.first.data(), rhs.first.size());
2816f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski                if (cmp < 0) return true;
2826f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski                if (cmp > 0) return false;
2836f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski                cmp = attr.name.compare(0, attr.name.size(), rhs.second.data(), rhs.second.size());
2846f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski                if (cmp < 0) return true;
2856f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski                return false;
2866f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski            }
2876f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    );
2886f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2896f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    if (iter != endIter && namespaceUri == iter->namespaceUri && name == iter->name) {
2906f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski        return iter;
2916f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    }
2926f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski    return endIter;
2936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}
2946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
295467f171315f9c2037fcd3eb5edcfabc40671bf7bAdam Lesinski} // namespace xml
2966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} // namespace aapt
2976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski
2986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#endif // AAPT_XML_PULL_PARSER_H
299