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 9 void IStreamRefDataSource::Reset() { 10 istream_ref_.clear(); 11 istream_ref_.seekg(0); 12 current_data_segment_.reset(); 13 } 14 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 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 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