upload_data_stream.cc revision c7f5f8508d98d5952d42ed7648c2a8f30a4da156
1// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "net/base/upload_data_stream.h" 6 7#include "base/logging.h" 8#include "net/base/io_buffer.h" 9#include "net/base/net_errors.h" 10 11namespace net { 12 13UploadDataStream::UploadDataStream(const UploadData* data) 14 : data_(data), 15 buf_(new IOBuffer(kBufSize)), 16 buf_len_(0), 17 next_element_(data->elements().begin()), 18 next_element_offset_(0), 19 next_element_remaining_(0), 20 total_size_(data->GetContentLength()), 21 current_position_(0) { 22 FillBuf(); 23} 24 25UploadDataStream::~UploadDataStream() { 26} 27 28void UploadDataStream::DidConsume(size_t num_bytes) { 29 // TODO(vandebo): Change back to a DCHECK when issue 27870 is resolved. 30 CHECK(num_bytes <= buf_len_); 31 32 buf_len_ -= num_bytes; 33 if (buf_len_) 34 memmove(buf_->data(), buf_->data() + num_bytes, buf_len_); 35 36 FillBuf(); 37 38 current_position_ += num_bytes; 39} 40 41void UploadDataStream::FillBuf() { 42 std::vector<UploadData::Element>::const_iterator end = 43 data_->elements().end(); 44 45 while (buf_len_ < kBufSize && next_element_ != end) { 46 bool advance_to_next_element = false; 47 48 const UploadData::Element& element = *next_element_; 49 50 size_t size_remaining = kBufSize - buf_len_; 51 if (element.type() == UploadData::TYPE_BYTES) { 52 const std::vector<char>& d = element.bytes(); 53 size_t count = d.size() - next_element_offset_; 54 55 size_t bytes_copied = std::min(count, size_remaining); 56 57 memcpy(buf_->data() + buf_len_, &d[next_element_offset_], bytes_copied); 58 buf_len_ += bytes_copied; 59 60 if (bytes_copied == count) { 61 advance_to_next_element = true; 62 } else { 63 next_element_offset_ += bytes_copied; 64 } 65 } else { 66 DCHECK(element.type() == UploadData::TYPE_FILE); 67 68 if (!next_element_stream_.IsOpen()) { 69 int flags = base::PLATFORM_FILE_OPEN | 70 base::PLATFORM_FILE_READ; 71 int rv = next_element_stream_.Open(element.file_path(), flags); 72 // If the file does not exist, that's technically okay.. we'll just 73 // upload an empty file. This is for consistency with Mozilla. 74 DLOG_IF(WARNING, rv != OK) << "Failed to open \"" 75 << element.file_path().value() 76 << "\" for reading: " << rv; 77 78 next_element_remaining_ = 0; // Default to reading nothing. 79 if (rv == OK) { 80 uint64 offset = element.file_range_offset(); 81 if (offset && next_element_stream_.Seek(FROM_BEGIN, offset) < 0) { 82 DLOG(WARNING) << "Failed to seek \"" << element.file_path().value() 83 << "\" to offset: " << offset; 84 } else { 85 next_element_remaining_ = element.file_range_length(); 86 } 87 } 88 } 89 90 int rv = 0; 91 int count = static_cast<int>(std::min( 92 static_cast<uint64>(size_remaining), next_element_remaining_)); 93 if (count > 0 && 94 (rv = next_element_stream_.Read(buf_->data() + buf_len_, 95 count, NULL)) > 0) { 96 buf_len_ += rv; 97 next_element_remaining_ -= rv; 98 } else { 99 advance_to_next_element = true; 100 } 101 } 102 103 if (advance_to_next_element) { 104 ++next_element_; 105 next_element_offset_ = 0; 106 next_element_stream_.Close(); 107 } 108 } 109} 110 111} // namespace net 112