blob: e87b94087450d63f7e15e6ca6f6ca94ce2281253 [file] [log] [blame]
Adam Lesinski7ad11102016-10-28 16:39:15 -07001/*
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>
52 inline const T* header() const {
53 if (header_size() >= sizeof(T)) {
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_ */