Chunk.h revision 136fd0764faf7a588b4a1b479d7a8cc6fe18fcc6
1/* 2 * Copyright (C) 2016 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 CHUNK_H_ 18#define CHUNK_H_ 19 20#include "android-base/logging.h" 21#include "android-base/macros.h" 22#include "utils/ByteOrder.h" 23 24#ifdef _WIN32 25#ifdef ERROR 26#undef ERROR 27#endif 28#endif 29 30#include "androidfw/ResourceTypes.h" 31 32namespace android { 33 34// Helpful wrapper around a ResChunk_header that provides getter methods 35// that handle endianness conversions and provide access to the data portion 36// of the chunk. 37class Chunk { 38 public: 39 explicit Chunk(const ResChunk_header* chunk) : device_chunk_(chunk) {} 40 41 // Returns the type of the chunk. Caller need not worry about endianness. 42 inline int type() const { return dtohs(device_chunk_->type); } 43 44 // Returns the size of the entire chunk. This can be useful for skipping 45 // over the entire chunk. Caller need not worry about endianness. 46 inline size_t size() const { return dtohl(device_chunk_->size); } 47 48 // Returns the size of the header. Caller need not worry about endianness. 49 inline size_t header_size() const { return dtohs(device_chunk_->headerSize); } 50 51 template <typename T, size_t MinSize = sizeof(T)> 52 inline const T* header() const { 53 if (header_size() >= MinSize) { 54 return reinterpret_cast<const T*>(device_chunk_); 55 } 56 return nullptr; 57 } 58 59 inline const void* data_ptr() const { 60 return reinterpret_cast<const uint8_t*>(device_chunk_) + header_size(); 61 } 62 63 inline size_t data_size() const { return size() - header_size(); } 64 65 private: 66 const ResChunk_header* device_chunk_; 67}; 68 69// Provides a Java style iterator over an array of ResChunk_header's. 70// Validation is performed while iterating. 71// The caller should check if there was an error during chunk validation 72// by calling HadError() and GetLastError() to get the reason for failure. 73// Example: 74// 75// ChunkIterator iter(data_ptr, data_len); 76// while (iter.HasNext()) { 77// const Chunk chunk = iter.Next(); 78// ... 79// } 80// 81// if (iter.HadError()) { 82// LOG(ERROR) << iter.GetLastError(); 83// } 84// 85class ChunkIterator { 86 public: 87 ChunkIterator(const void* data, size_t len) 88 : next_chunk_(reinterpret_cast<const ResChunk_header*>(data)), 89 len_(len), 90 last_error_(nullptr) { 91 CHECK(next_chunk_ != nullptr) << "data can't be nullptr"; 92 VerifyNextChunk(); 93 } 94 95 Chunk Next(); 96 inline bool HasNext() const { return !HadError() && len_ != 0; }; 97 inline bool HadError() const { return last_error_ != nullptr; } 98 inline std::string GetLastError() const { return last_error_; } 99 100 private: 101 DISALLOW_COPY_AND_ASSIGN(ChunkIterator); 102 103 // Returns false if there was an error. 104 bool VerifyNextChunk(); 105 106 const ResChunk_header* next_chunk_; 107 size_t len_; 108 const char* last_error_; 109}; 110 111} // namespace android 112 113#endif /* CHUNK_H_ */ 114