1 /*
2 * Copyright (C) 2017 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 #include "androidfw/BigBufferStream.h"
18
19 #include <algorithm>
20
21 namespace android {
22
23 //
24 // BigBufferInputStream
25 //
26
Next(const void ** data,size_t * size)27 bool BigBufferInputStream::Next(const void** data, size_t* size) {
28 if (iter_ == buffer_->end()) {
29 return false;
30 }
31
32 if (offset_ == iter_->size) {
33 ++iter_;
34 if (iter_ == buffer_->end()) {
35 return false;
36 }
37 offset_ = 0;
38 }
39
40 *data = iter_->buffer.get() + offset_;
41 *size = iter_->size - offset_;
42 bytes_read_ += iter_->size - offset_;
43 offset_ = iter_->size;
44 return true;
45 }
46
BackUp(size_t count)47 void BigBufferInputStream::BackUp(size_t count) {
48 if (count > offset_) {
49 bytes_read_ -= offset_;
50 offset_ = 0;
51 } else {
52 offset_ -= count;
53 bytes_read_ -= count;
54 }
55 }
56
CanRewind() const57 bool BigBufferInputStream::CanRewind() const {
58 return true;
59 }
60
Rewind()61 bool BigBufferInputStream::Rewind() {
62 iter_ = buffer_->begin();
63 offset_ = 0;
64 bytes_read_ = 0;
65 return true;
66 }
67
ByteCount() const68 size_t BigBufferInputStream::ByteCount() const {
69 return bytes_read_;
70 }
71
HadError() const72 bool BigBufferInputStream::HadError() const {
73 return false;
74 }
75
TotalSize() const76 size_t BigBufferInputStream::TotalSize() const {
77 return buffer_->size();
78 }
79
ReadFullyAtOffset(void * data,size_t byte_count,off64_t offset)80 bool BigBufferInputStream::ReadFullyAtOffset(void* data, size_t byte_count, off64_t offset) {
81 if (byte_count == 0) {
82 return true;
83 }
84 if (offset < 0) {
85 return false;
86 }
87 if (offset > std::numeric_limits<off64_t>::max() - byte_count) {
88 return false;
89 }
90 if (offset + byte_count > buffer_->size()) {
91 return false;
92 }
93 auto p = reinterpret_cast<uint8_t*>(data);
94 for (auto iter = buffer_->begin(); iter != buffer_->end() && byte_count > 0; ++iter) {
95 if (offset < iter->size) {
96 size_t to_read = std::min(byte_count, (size_t)(iter->size - offset));
97 memcpy(p, iter->buffer.get() + offset, to_read);
98 byte_count -= to_read;
99 p += to_read;
100 offset = 0;
101 } else {
102 offset -= iter->size;
103 }
104 }
105 return byte_count == 0;
106 }
107
108 //
109 // BigBufferOutputStream
110 //
111
Next(void ** data,size_t * size)112 bool BigBufferOutputStream::Next(void** data, size_t* size) {
113 *data = buffer_->NextBlock(size);
114 return true;
115 }
116
BackUp(size_t count)117 void BigBufferOutputStream::BackUp(size_t count) {
118 buffer_->BackUp(count);
119 }
120
ByteCount() const121 size_t BigBufferOutputStream::ByteCount() const {
122 return buffer_->size();
123 }
124
HadError() const125 bool BigBufferOutputStream::HadError() const {
126 return false;
127 }
128
129 } // namespace android
130