Home | History | Annotate | Download | only in base
      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