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_RES_CHUNK_PULL_PARSER_H 186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#define AAPT_RES_CHUNK_PULL_PARSER_H 196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <androidfw/ResourceTypes.h> 216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#include <string> 226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 236f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskinamespace aapt { 246f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 256f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski/** 266f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * A pull parser, modeled after XmlPullParser, that reads 276f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * android::ResChunk_header structs from a block of data. 286f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 296f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * An android::ResChunk_header specifies a type, headerSize, 306f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * and size. The pull parser will verify that the chunk's size 316f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * doesn't extend beyond the available data, and will iterate 326f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * over each chunk in the given block of data. 336f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * 346f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Processing nested chunks is done by creating a new ResChunkPullParser 356f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * pointing to the data portion of a chunk. 366f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 376f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiclass ResChunkPullParser { 386f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskipublic: 396f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski enum class Event { 406f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski StartDocument, 416f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski EndDocument, 426f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski BadDocument, 436f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 446f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski Chunk, 456f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski }; 466f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 476f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski /** 486f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Returns false if the event is EndDocument or BadDocument. 496f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 506f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski static bool isGoodEvent(Event event); 516f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 526f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski /** 536f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Create a ResChunkPullParser to read android::ResChunk_headers 546f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * from the memory pointed to by data, of len bytes. 556f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 566f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ResChunkPullParser(const void* data, size_t len); 576f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 586f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski ResChunkPullParser(const ResChunkPullParser&) = delete; 596f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 606f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski Event getEvent() const; 616f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const std::string& getLastError() const; 626f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const android::ResChunk_header* getChunk() const; 636f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 646f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski /** 656f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski * Move to the next android::ResChunk_header. 666f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski */ 676f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski Event next(); 686f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 696f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiprivate: 706f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski Event mEvent; 716f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const android::ResChunk_header* mData; 726f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski size_t mLen; 736f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski const android::ResChunk_header* mCurrentChunk; 746f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski std::string mLastError; 756f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski}; 766f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 77769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskitemplate <typename T> 78769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskiinline static const T* convertTo(const android::ResChunk_header* chunk) { 79769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski if (chunk->headerSize < sizeof(T)) { 80769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return nullptr; 81769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski } 82769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return reinterpret_cast<const T*>(chunk); 83769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 84769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 85769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskiinline static const uint8_t* getChunkData(const android::ResChunk_header& chunk) { 86769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return reinterpret_cast<const uint8_t*>(&chunk) + chunk.headerSize; 87769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 88769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 89769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinskiinline static size_t getChunkDataLen(const android::ResChunk_header& chunk) { 90769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski return chunk.size - chunk.headerSize; 91769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski} 92769de98f2dd41bfe39a1c9f76aefd1ad58942733Adam Lesinski 936f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski// 946f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski// Implementation 956f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski// 966f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 976f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline bool ResChunkPullParser::isGoodEvent(ResChunkPullParser::Event event) { 986f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return event != Event::EndDocument && event != Event::BadDocument; 996f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1006f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1016f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline ResChunkPullParser::ResChunkPullParser(const void* data, size_t len) : 1026f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mEvent(Event::StartDocument), 1036f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mData(reinterpret_cast<const android::ResChunk_header*>(data)), 1046f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mLen(len), 1056f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski mCurrentChunk(nullptr) { 1066f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1076f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1086f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline ResChunkPullParser::Event ResChunkPullParser::getEvent() const { 1096f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return mEvent; 1106f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1116f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1126f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline const std::string& ResChunkPullParser::getLastError() const { 1136f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return mLastError; 1146f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1156f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1166f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinskiinline const android::ResChunk_header* ResChunkPullParser::getChunk() const { 1176f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski return mCurrentChunk; 1186f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} 1196f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1206f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski} // namespace aapt 1216f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski 1226f6ceb7e1456698b1f33e04536bfb3227f9fcfcbAdam Lesinski#endif // AAPT_RES_CHUNK_PULL_PARSER_H 123