xref: /aosp_15_r20/external/image_io/src/base/istream_ref_data_source.cc (revision ca0779eb572efbbfda2e47f806647c3c7eeea8c3)
1 #include "image_io/base/istream_ref_data_source.h"
2 
3 #include <algorithm>
4 
5 #include "image_io/base/data_destination.h"
6 #include "image_io/base/data_segment.h"
7 
8 namespace photos_editing_formats {
9 namespace image_io {
10 
Reset()11 void IStreamRefDataSource::Reset() {
12   istream_ref_.clear();
13   istream_ref_.seekg(0);
14   current_data_segment_.reset();
15 }
16 
GetDataSegment(size_t begin,size_t min_size)17 std::shared_ptr<DataSegment> IStreamRefDataSource::GetDataSegment(
18     size_t begin, size_t min_size) {
19   if (current_data_segment_ && current_data_segment_->Contains(begin)) {
20     return current_data_segment_;
21   }
22   current_data_segment_ = Read(begin, min_size);
23   return current_data_segment_;
24 }
25 
TransferData(const DataRange & data_range,size_t best_size,DataDestination * data_destination)26 DataSource::TransferDataResult IStreamRefDataSource::TransferData(
27     const DataRange &data_range, size_t best_size,
28     DataDestination *data_destination) {
29   bool data_transferred = false;
30   DataDestination::TransferStatus status = DataDestination::kTransferDone;
31   if (data_destination && data_range.IsValid()) {
32     size_t min_size = std::min(data_range.GetLength(), best_size);
33     if (current_data_segment_ &&
34         current_data_segment_->GetLength() >= min_size &&
35         current_data_segment_->GetDataRange().Contains(data_range)) {
36       status = data_destination->Transfer(data_range, *current_data_segment_);
37       data_transferred = true;
38     } else {
39       istream_ref_.clear();
40       size_t chunk_size = min_size;
41       for (size_t begin = data_range.GetBegin(); begin < data_range.GetEnd();
42            begin += chunk_size) {
43         size_t segment_length = 0;
44         size_t end = std::min(data_range.GetEnd(), begin + chunk_size);
45         std::shared_ptr<DataSegment> data_segment = Read(begin, end - begin);
46         if (data_segment) {
47           segment_length = data_segment->GetLength();
48           if (segment_length) {
49             status = data_destination->Transfer(data_segment->GetDataRange(),
50                                                 *data_segment);
51             data_transferred = true;
52           }
53         }
54         if (status != DataDestination::kTransferOk || segment_length == 0) {
55           break;
56         }
57       }
58     }
59   }
60   if (data_transferred) {
61     return status == DataDestination::kTransferError ? kTransferDataError
62                                                      : kTransferDataSuccess;
63   } else {
64     return data_destination ? kTransferDataNone : kTransferDataError;
65   }
66 }
67 
Read(size_t begin,size_t count)68 std::shared_ptr<DataSegment> IStreamRefDataSource::Read(size_t begin,
69                                                         size_t count) {
70   std::shared_ptr<DataSegment> shared_data_segment;
71   istream_ref_.seekg(begin);
72   if (istream_ref_.rdstate() == std::ios_base::goodbit) {
73     Byte *buffer = new Byte[count];
74     istream_ref_.read(reinterpret_cast<char *>(buffer), count);
75     size_t bytes_read = istream_ref_.gcount();
76     shared_data_segment =
77         DataSegment::Create(DataRange(begin, begin + bytes_read), buffer);
78   }
79   return shared_data_segment;
80 }
81 
82 }  // namespace image_io
83 }  // namespace photos_editing_formats
84