1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef AAPT_RES_CHUNK_PULL_PARSER_H 18#define AAPT_RES_CHUNK_PULL_PARSER_H 19 20#include <androidfw/ResourceTypes.h> 21#include <string> 22 23namespace aapt { 24 25/** 26 * A pull parser, modeled after XmlPullParser, that reads 27 * android::ResChunk_header structs from a block of data. 28 * 29 * An android::ResChunk_header specifies a type, headerSize, 30 * and size. The pull parser will verify that the chunk's size 31 * doesn't extend beyond the available data, and will iterate 32 * over each chunk in the given block of data. 33 * 34 * Processing nested chunks is done by creating a new ResChunkPullParser 35 * pointing to the data portion of a chunk. 36 */ 37class ResChunkPullParser { 38public: 39 enum class Event { 40 StartDocument, 41 EndDocument, 42 BadDocument, 43 44 Chunk, 45 }; 46 47 /** 48 * Returns false if the event is EndDocument or BadDocument. 49 */ 50 static bool isGoodEvent(Event event); 51 52 /** 53 * Create a ResChunkPullParser to read android::ResChunk_headers 54 * from the memory pointed to by data, of len bytes. 55 */ 56 ResChunkPullParser(const void* data, size_t len); 57 58 ResChunkPullParser(const ResChunkPullParser&) = delete; 59 60 Event getEvent() const; 61 const std::string& getLastError() const; 62 const android::ResChunk_header* getChunk() const; 63 64 /** 65 * Move to the next android::ResChunk_header. 66 */ 67 Event next(); 68 69private: 70 Event mEvent; 71 const android::ResChunk_header* mData; 72 size_t mLen; 73 const android::ResChunk_header* mCurrentChunk; 74 std::string mLastError; 75}; 76 77template <typename T> 78inline static const T* convertTo(const android::ResChunk_header* chunk) { 79 if (chunk->headerSize < sizeof(T)) { 80 return nullptr; 81 } 82 return reinterpret_cast<const T*>(chunk); 83} 84 85inline static const uint8_t* getChunkData(const android::ResChunk_header& chunk) { 86 return reinterpret_cast<const uint8_t*>(&chunk) + chunk.headerSize; 87} 88 89inline static size_t getChunkDataLen(const android::ResChunk_header& chunk) { 90 return chunk.size - chunk.headerSize; 91} 92 93// 94// Implementation 95// 96 97inline bool ResChunkPullParser::isGoodEvent(ResChunkPullParser::Event event) { 98 return event != Event::EndDocument && event != Event::BadDocument; 99} 100 101inline ResChunkPullParser::ResChunkPullParser(const void* data, size_t len) : 102 mEvent(Event::StartDocument), 103 mData(reinterpret_cast<const android::ResChunk_header*>(data)), 104 mLen(len), 105 mCurrentChunk(nullptr) { 106} 107 108inline ResChunkPullParser::Event ResChunkPullParser::getEvent() const { 109 return mEvent; 110} 111 112inline const std::string& ResChunkPullParser::getLastError() const { 113 return mLastError; 114} 115 116inline const android::ResChunk_header* ResChunkPullParser::getChunk() const { 117 return mCurrentChunk; 118} 119 120} // namespace aapt 121 122#endif // AAPT_RES_CHUNK_PULL_PARSER_H 123