1 /*
2  * Copyright (C) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "heif_stream.h"
17 #include "heif_constant.h"
18 #include "securec.h"
19 
20 #include <sstream>
21 
22 const uint8_t BUFFER_INDEX_FOUR = 4;
23 const uint8_t BUFFER_INDEX_FIVE = 5;
24 const uint8_t BUFFER_INDEX_SIX = 6;
25 const uint8_t BUFFER_INDEX_SEVEN = 7;
26 
27 namespace OHOS {
28 namespace ImagePlugin {
HeifBufferInputStream(const uint8_t * data,size_t size,bool needCopy)29 HeifBufferInputStream::HeifBufferInputStream(const uint8_t *data, size_t size, bool needCopy)
30     : length_(size), pos_(0), copied_(needCopy)
31 {
32     if (copied_) {
33         auto *copiedData = new uint8_t[length_];
34         memcpy_s(copiedData, length_, data, length_);
35         data_ = copiedData;
36     } else {
37         data_ = data;
38     }
39 }
40 
~HeifBufferInputStream()41 HeifBufferInputStream::~HeifBufferInputStream()
42 {
43     if (copied_) {
44         delete[] data_;
45     }
46 }
47 
Tell() const48 int64_t HeifBufferInputStream::Tell() const
49 {
50     return pos_;
51 }
52 
CheckSize(size_t target_size,int64_t end)53 bool HeifBufferInputStream::CheckSize(size_t target_size, int64_t end)
54 {
55     auto posAfterRead = Tell() + static_cast<int64_t>(target_size);
56     return (end < 0 || posAfterRead <= end) && static_cast<size_t>(posAfterRead) <= length_;
57 }
58 
Read(void * data,size_t size)59 bool HeifBufferInputStream::Read(void *data, size_t size)
60 {
61     auto end_pos = static_cast<size_t>(pos_) + size;
62     if (static_cast<size_t>(end_pos) > length_) {
63         return false;
64     }
65 
66     if (memcpy_s(data, size, &data_[pos_], size) != EOK) {
67         return false;
68     }
69     pos_ = pos_ + static_cast<int64_t>(size);
70 
71     return true;
72 }
73 
Seek(int64_t position)74 bool HeifBufferInputStream::Seek(int64_t position)
75 {
76     if (static_cast<size_t>(position) > length_ || position < 0)
77         return false;
78 
79     pos_ = position;
80     return true;
81 }
82 
HeifStreamReader(std::shared_ptr<HeifInputStream> stream,int64_t start,size_t length)83 HeifStreamReader::HeifStreamReader(std::shared_ptr<HeifInputStream> stream, int64_t start, size_t length)
84     : inputStream_(std::move(stream)), start_(start)
85 {
86     end_ = start_ + static_cast<int64_t>(length);
87 }
88 
Read8()89 uint8_t HeifStreamReader::Read8()
90 {
91     if (!CheckSize(UINT8_BYTES_NUM)) {
92         return 0;
93     }
94     uint8_t buf;
95     auto stream = GetStream();
96     bool success = stream->Read(&buf, UINT8_BYTES_NUM);
97     if (!success) {
98         SetError(true);
99         return 0;
100     }
101     return buf;
102 }
103 
Read16()104 uint16_t HeifStreamReader::Read16()
105 {
106     if (!CheckSize(UINT16_BYTES_NUM)) {
107         return 0;
108     }
109     uint8_t buf[UINT16_BYTES_NUM];
110     auto stream = GetStream();
111     bool success = stream->Read(buf, UINT16_BYTES_NUM);
112     if (!success) {
113         SetError(true);
114         return 0;
115     }
116     return static_cast<uint16_t>((buf[BUFFER_INDEX_ZERO] << ONE_BYTE_SHIFT) | (buf[BUFFER_INDEX_ONE]));
117 }
118 
Read32()119 uint32_t HeifStreamReader::Read32()
120 {
121     if (!CheckSize(UINT32_BYTES_NUM)) {
122         return 0;
123     }
124     uint8_t buf[UINT32_BYTES_NUM];
125     auto stream = GetStream();
126     bool success = stream->Read(buf, UINT32_BYTES_NUM);
127     if (!success) {
128         SetError(true);
129         return 0;
130     }
131     return static_cast<uint32_t>((buf[BUFFER_INDEX_ZERO] << THREE_BYTES_SHIFT) |
132         (buf[BUFFER_INDEX_ONE] << TWO_BYTES_SHIFT) |
133         (buf[BUFFER_INDEX_TWO] << ONE_BYTE_SHIFT) |
134         (buf[BUFFER_INDEX_THREE]));
135 }
136 
Read64()137 uint64_t HeifStreamReader::Read64()
138 {
139     if (!CheckSize(UINT64_BYTES_NUM)) {
140         return 0;
141     }
142     uint8_t buf[UINT64_BYTES_NUM];
143     auto stream = GetStream();
144     bool success = stream->Read(buf, UINT64_BYTES_NUM);
145     if (!success) {
146         SetError(true);
147         return 0;
148     }
149     return static_cast<uint64_t>(((uint64_t)buf[BUFFER_INDEX_ZERO] << SEVEN_BYTES_SHIFT) |
150         ((uint64_t)buf[BUFFER_INDEX_ONE] << SIX_BYTES_SHIFT) |
151         ((uint64_t)buf[BUFFER_INDEX_TWO] << FIVE_BYTES_SHIFT) |
152         ((uint64_t)buf[BUFFER_INDEX_THREE] << FOUR_BYTES_SHIFT) |
153         ((uint64_t)buf[BUFFER_INDEX_FOUR] << THREE_BYTES_SHIFT) |
154         ((uint64_t)buf[BUFFER_INDEX_FIVE] << TWO_BYTES_SHIFT) |
155         ((uint64_t)buf[BUFFER_INDEX_SIX] << ONE_BYTE_SHIFT) |
156         ((uint64_t)buf[BUFFER_INDEX_SEVEN]));
157 }
158 
ReadData(uint8_t * data,size_t size)159 bool HeifStreamReader::ReadData(uint8_t *data, size_t size)
160 {
161     if (!CheckSize(size)) {
162         return false;
163     }
164     bool res = GetStream()->Read(data, size);
165     if (!res) {
166         SetError(true);
167     }
168     return res;
169 }
170 
ReadString()171 std::string HeifStreamReader::ReadString()
172 {
173     if (IsAtEnd()) {
174         return {};
175     }
176     std::stringstream strStream;
177     auto stream = GetStream();
178     char strChar = UINT8_BYTES_NUM;
179     while (strChar != 0) {
180         if (!CheckSize(UINT8_BYTES_NUM)) {
181             return {};
182         }
183         bool res = stream->Read(&strChar, UINT8_BYTES_NUM);
184         if (!res) {
185             SetError(true);
186             return {};
187         }
188         if (strChar != 0) {
189             strStream << strChar;
190         }
191     }
192     return strStream.str();
193 }
194 
CheckSize(size_t size)195 bool HeifStreamReader::CheckSize(size_t size)
196 {
197     bool res = inputStream_->CheckSize(size, end_);
198     if (!res) {
199         SetError(true);
200     }
201     return res;
202 }
203 
CheckSize(size_t size)204 void HeifStreamWriter::CheckSize(size_t size)
205 {
206     size_t posAfterMove = position_ + size;
207     if (posAfterMove > data_.size()) {
208         data_.resize(posAfterMove);
209     }
210 }
211 
Write8(uint8_t value)212 void HeifStreamWriter::Write8(uint8_t value)
213 {
214     if (position_ == data_.size()) {
215         data_.push_back(value);
216         position_++;
217     } else {
218         data_[position_++] = value;
219     }
220 }
221 
Write16(uint16_t value)222 void HeifStreamWriter::Write16(uint16_t value)
223 {
224     CheckSize(UINT16_BYTES_NUM);
225     data_[position_++] = uint8_t((value >> ONE_BYTE_SHIFT) & 0xFF);
226     data_[position_++] = uint8_t(value & 0xFF);
227 }
228 
Write32(uint32_t value)229 void HeifStreamWriter::Write32(uint32_t value)
230 {
231     CheckSize(UINT32_BYTES_NUM);
232     data_[position_++] = uint8_t((value >> THREE_BYTES_SHIFT) & 0xFF);
233     data_[position_++] = uint8_t((value >> TWO_BYTES_SHIFT) & 0xFF);
234     data_[position_++] = uint8_t((value >> ONE_BYTE_SHIFT) & 0xFF);
235     data_[position_++] = uint8_t(value & 0xFF);
236 }
237 
Write64(uint64_t value)238 void HeifStreamWriter::Write64(uint64_t value)
239 {
240     CheckSize(UINT64_BYTES_NUM);
241     data_[position_++] = uint8_t((value >> SEVEN_BYTES_SHIFT) & 0xFF);
242     data_[position_++] = uint8_t((value >> SIX_BYTES_SHIFT) & 0xFF);
243     data_[position_++] = uint8_t((value >> FIVE_BYTES_SHIFT) & 0xFF);
244     data_[position_++] = uint8_t((value >> FOUR_BYTES_SHIFT) & 0xFF);
245     data_[position_++] = uint8_t((value >> THREE_BYTES_SHIFT) & 0xFF);
246     data_[position_++] = uint8_t((value >> TWO_BYTES_SHIFT) & 0xFF);
247     data_[position_++] = uint8_t((value >> ONE_BYTE_SHIFT) & 0xFF);
248     data_[position_++] = uint8_t(value & 0xFF);
249 }
250 
Write(int size,uint64_t value)251 void HeifStreamWriter::Write(int size, uint64_t value)
252 {
253     switch (size) {
254         case UINT8_BYTES_NUM: {
255             Write8((uint8_t) value);
256             break;
257         }
258         case UINT16_BYTES_NUM: {
259             Write16((uint16_t) value);
260             break;
261         }
262         case UINT32_BYTES_NUM: {
263             Write32((uint32_t) value);
264             break;
265         }
266         case UINT64_BYTES_NUM:
267             Write64((uint64_t) value);
268             break;
269         default:
270             break;
271     }
272 }
273 
Write(const std::string & str)274 void HeifStreamWriter::Write(const std::string &str)
275 {
276     CheckSize(str.size() + UINT8_BYTES_NUM);
277     for (char ch : str) {
278         data_[position_++] = ch;
279     }
280     data_[position_++] = 0;
281 }
282 
Write(const std::vector<uint8_t> & data)283 void HeifStreamWriter::Write(const std::vector<uint8_t> &data)
284 {
285     CheckSize(data.size());
286     if (EOK != memcpy_s(data_.data() + position_, data_.size() - position_, data.data(), data.size())) {
287         return;
288     }
289     position_ += data.size();
290 }
291 
Skip(size_t skipSize)292 void HeifStreamWriter::Skip(size_t skipSize)
293 {
294     CheckSize(skipSize);
295     position_ += skipSize;
296 }
297 
Insert(size_t insertSize)298 void HeifStreamWriter::Insert(size_t insertSize)
299 {
300     if (insertSize == 0) {
301         return;
302     }
303     size_t sizeToMove = data_.size() - position_;
304     void *pCurrent = data_.data() + position_;
305     void *pAfterMove = reinterpret_cast<uint8_t*>(pCurrent) + insertSize;
306     data_.resize(data_.size() + insertSize);
307     if (EOK != memmove_s(pAfterMove, sizeToMove, pCurrent, sizeToMove)) {
308         return;
309     }
310 }
311 } // namespace ImagePlugin
312 } // namespace OHOS
313