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_IO_DATA_H
18#define AAPT_IO_DATA_H
19
20#include <memory>
21
22#include "android-base/macros.h"
23#include "utils/FileMap.h"
24
25#include "io/Io.h"
26
27namespace aapt {
28namespace io {
29
30// Interface for a block of contiguous memory. An instance of this interface owns the data.
31class IData : public KnownSizeInputStream {
32 public:
33  virtual ~IData() = default;
34
35  virtual const void* data() const = 0;
36  virtual size_t size() const = 0;
37
38  virtual size_t TotalSize() const override {
39    return size();
40  }
41};
42
43class DataSegment : public IData {
44 public:
45  explicit DataSegment(std::unique_ptr<IData> data, size_t offset, size_t len)
46      : data_(std::move(data)), offset_(offset), len_(len), next_read_(offset) {}
47  virtual ~DataSegment() = default;
48
49  const void* data() const override {
50    return static_cast<const uint8_t*>(data_->data()) + offset_;
51  }
52
53  size_t size() const override { return len_; }
54
55  bool Next(const void** data, size_t* size) override {
56    if (next_read_ == offset_ + len_) {
57      return false;
58    }
59    *data = static_cast<const uint8_t*>(data_->data()) + next_read_;
60    *size = len_ - (next_read_ - offset_);
61    next_read_ = offset_ + len_;
62    return true;
63  }
64
65  void BackUp(size_t count) override {
66    if (count > next_read_ - offset_) {
67      next_read_ = offset_;
68    } else {
69      next_read_ -= count;
70    }
71  }
72
73  bool CanRewind() const override { return true; }
74
75  bool Rewind() override {
76    next_read_ = offset_;
77    return true;
78  }
79
80  size_t ByteCount() const override { return next_read_ - offset_; }
81
82  bool HadError() const override { return false; }
83
84 private:
85  DISALLOW_COPY_AND_ASSIGN(DataSegment);
86
87  std::unique_ptr<IData> data_;
88  size_t offset_;
89  size_t len_;
90  size_t next_read_;
91};
92
93// Implementation of IData that exposes a memory mapped file.
94// The mmapped file is owned by this object.
95class MmappedData : public IData {
96 public:
97  explicit MmappedData(android::FileMap&& map) : map_(std::forward<android::FileMap>(map)) {}
98  virtual ~MmappedData() = default;
99
100  const void* data() const override { return map_.getDataPtr(); }
101
102  size_t size() const override { return map_.getDataLength(); }
103
104  bool Next(const void** data, size_t* size) override {
105    if (next_read_ == map_.getDataLength()) {
106      return false;
107    }
108    *data = reinterpret_cast<const uint8_t*>(map_.getDataPtr()) + next_read_;
109    *size = map_.getDataLength() - next_read_;
110    next_read_ = map_.getDataLength();
111    return true;
112  }
113
114  void BackUp(size_t count) override {
115    if (count > next_read_) {
116      next_read_ = 0;
117    } else {
118      next_read_ -= count;
119    }
120  }
121
122  bool CanRewind() const override { return true; }
123
124  bool Rewind() override {
125    next_read_ = 0;
126    return true;
127  }
128
129  size_t ByteCount() const override { return next_read_; }
130
131  bool HadError() const override { return false; }
132
133 private:
134  DISALLOW_COPY_AND_ASSIGN(MmappedData);
135
136  android::FileMap map_;
137  size_t next_read_ = 0;
138};
139
140// Implementation of IData that exposes a block of memory that was malloc'ed (new'ed).
141// The memory is owned by this object.
142class MallocData : public IData {
143 public:
144  MallocData(std::unique_ptr<const uint8_t[]> data, size_t size)
145      : data_(std::move(data)), size_(size) {}
146  virtual ~MallocData() = default;
147
148  const void* data() const override { return data_.get(); }
149
150  size_t size() const override { return size_; }
151
152  bool Next(const void** data, size_t* size) override {
153    if (next_read_ == size_) {
154      return false;
155    }
156    *data = data_.get() + next_read_;
157    *size = size_ - next_read_;
158    next_read_ = size_;
159    return true;
160  }
161
162  void BackUp(size_t count) override {
163    if (count > next_read_) {
164      next_read_ = 0;
165    } else {
166      next_read_ -= count;
167    }
168  }
169
170  bool CanRewind() const override { return true; }
171
172  bool Rewind() override {
173    next_read_ = 0;
174    return true;
175  }
176
177  size_t ByteCount() const override { return next_read_; }
178
179  bool HadError() const override { return false; }
180
181 private:
182  DISALLOW_COPY_AND_ASSIGN(MallocData);
183
184  std::unique_ptr<const uint8_t[]> data_;
185  size_t size_;
186  size_t next_read_ = 0;
187};
188
189// When mmap fails because the file has length 0, we use the EmptyData to simulate data of length 0.
190class EmptyData : public IData {
191 public:
192  virtual ~EmptyData() = default;
193
194  const void* data() const override {
195    static const uint8_t d = 0;
196    return &d;
197  }
198
199  size_t size() const override { return 0u; }
200
201  bool Next(const void** /*data*/, size_t* /*size*/) override { return false; }
202
203  void BackUp(size_t /*count*/) override {}
204
205  bool CanRewind() const override { return true; }
206
207  bool Rewind() override { return true; }
208
209  size_t ByteCount() const override { return 0u; }
210
211  bool HadError() const override { return false; }
212};
213
214}  // namespace io
215}  // namespace aapt
216
217#endif /* AAPT_IO_DATA_H */
218