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