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