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