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