| Index: net/base/file_input_stream_win.cc
|
| ===================================================================
|
| --- net/base/file_input_stream_win.cc (revision 4450)
|
| +++ net/base/file_input_stream_win.cc (working copy)
|
| @@ -1,230 +0,0 @@
|
| -// Copyright (c) 2008 The Chromium Authors. All rights reserved. Use of this
|
| -// source code is governed by a BSD-style license that can be found in the
|
| -// LICENSE file.
|
| -
|
| -#include "net/base/file_input_stream.h"
|
| -
|
| -#include <windows.h>
|
| -
|
| -#include "base/logging.h"
|
| -#include "base/message_loop.h"
|
| -#include "net/base/net_errors.h"
|
| -
|
| -namespace net {
|
| -
|
| -// Ensure that we can just use our Whence values directly.
|
| -COMPILE_ASSERT(FROM_BEGIN == FILE_BEGIN, bad_whence_begin);
|
| -COMPILE_ASSERT(FROM_CURRENT == FILE_CURRENT, bad_whence_current);
|
| -COMPILE_ASSERT(FROM_END == FILE_END, bad_whence_end);
|
| -
|
| -static void SetOffset(OVERLAPPED* overlapped, const LARGE_INTEGER& offset) {
|
| - overlapped->Offset = offset.LowPart;
|
| - overlapped->OffsetHigh = offset.HighPart;
|
| -}
|
| -
|
| -static void IncrementOffset(OVERLAPPED* overlapped, DWORD count) {
|
| - LARGE_INTEGER offset;
|
| - offset.LowPart = overlapped->Offset;
|
| - offset.HighPart = overlapped->OffsetHigh;
|
| - offset.QuadPart += static_cast<LONGLONG>(count);
|
| - SetOffset(overlapped, offset);
|
| -}
|
| -
|
| -static int MapErrorCode(DWORD err) {
|
| - switch (err) {
|
| - case ERROR_FILE_NOT_FOUND:
|
| - case ERROR_PATH_NOT_FOUND:
|
| - return ERR_FILE_NOT_FOUND;
|
| - case ERROR_ACCESS_DENIED:
|
| - return ERR_ACCESS_DENIED;
|
| - case ERROR_SUCCESS:
|
| - return OK;
|
| - default:
|
| - LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED";
|
| - return ERR_FAILED;
|
| - }
|
| -}
|
| -
|
| -// FileInputStream::AsyncContext ----------------------------------------------
|
| -
|
| -class FileInputStream::AsyncContext : public MessageLoopForIO::IOHandler {
|
| - public:
|
| - AsyncContext(FileInputStream* owner)
|
| - : owner_(owner), overlapped_(), callback_(NULL) {
|
| - overlapped_.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
| - }
|
| -
|
| - ~AsyncContext() {
|
| - if (callback_)
|
| - MessageLoopForIO::current()->RegisterIOContext(&overlapped_, NULL);
|
| - CloseHandle(overlapped_.hEvent);
|
| - }
|
| -
|
| - void IOCompletionIsPending(CompletionCallback* callback);
|
| -
|
| - OVERLAPPED* overlapped() { return &overlapped_; }
|
| - CompletionCallback* callback() const { return callback_; }
|
| -
|
| - private:
|
| - // MessageLoopForIO::IOHandler implementation:
|
| - virtual void OnIOCompleted(OVERLAPPED* context, DWORD bytes_read,
|
| - DWORD error);
|
| -
|
| - FileInputStream* owner_;
|
| - OVERLAPPED overlapped_;
|
| - CompletionCallback* callback_;
|
| -};
|
| -
|
| -void FileInputStream::AsyncContext::IOCompletionIsPending(
|
| - CompletionCallback* callback) {
|
| - DCHECK(!callback_);
|
| - callback_ = callback;
|
| -
|
| - MessageLoopForIO::current()->RegisterIOContext(&overlapped_, this);
|
| -}
|
| -
|
| -void FileInputStream::AsyncContext::OnIOCompleted(OVERLAPPED* context,
|
| - DWORD bytes_read,
|
| - DWORD error) {
|
| - DCHECK(&overlapped_ == context);
|
| - DCHECK(callback_);
|
| -
|
| - MessageLoopForIO::current()->RegisterIOContext(&overlapped_, NULL);
|
| -
|
| - HANDLE handle = owner_->handle_;
|
| -
|
| - int result = static_cast<int>(bytes_read);
|
| - if (error && error != ERROR_HANDLE_EOF)
|
| - result = MapErrorCode(error);
|
| -
|
| - if (bytes_read)
|
| - IncrementOffset(&overlapped_, bytes_read);
|
| -
|
| - CompletionCallback* temp = NULL;
|
| - std::swap(temp, callback_);
|
| - temp->Run(result);
|
| -}
|
| -
|
| -// FileInputStream ------------------------------------------------------------
|
| -
|
| -FileInputStream::FileInputStream() : handle_(INVALID_HANDLE_VALUE) {
|
| -}
|
| -
|
| -FileInputStream::~FileInputStream() {
|
| - Close();
|
| -}
|
| -
|
| -void FileInputStream::Close() {
|
| - if (handle_ != INVALID_HANDLE_VALUE) {
|
| - CloseHandle(handle_);
|
| - handle_ = INVALID_HANDLE_VALUE;
|
| - }
|
| - async_context_.reset();
|
| -}
|
| -
|
| -int FileInputStream::Open(const std::wstring& path, bool asynchronous_mode) {
|
| - if (IsOpen()) {
|
| - DLOG(FATAL) << "File is already open!";
|
| - return ERR_UNEXPECTED;
|
| - }
|
| -
|
| - // Optimize for streaming, not seeking. If someone does a lot of random
|
| - // access operations, then we should consider revising this.
|
| - DWORD create_file_flags = FILE_FLAG_SEQUENTIAL_SCAN;
|
| -
|
| - if (asynchronous_mode)
|
| - create_file_flags |= FILE_FLAG_OVERLAPPED;
|
| -
|
| - handle_ =
|
| - CreateFile(path.c_str(), GENERIC_READ | SYNCHRONIZE,
|
| - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
| - NULL, OPEN_EXISTING, create_file_flags, NULL);
|
| - if (handle_ == INVALID_HANDLE_VALUE) {
|
| - DWORD error = GetLastError();
|
| - LOG(WARNING) << "Failed to open file: " << error;
|
| - return MapErrorCode(error);
|
| - }
|
| -
|
| - if (asynchronous_mode) {
|
| - async_context_.reset(new AsyncContext(this));
|
| - MessageLoopForIO::current()->RegisterIOHandler(handle_,
|
| - async_context_.get());
|
| - }
|
| -
|
| - return OK;
|
| -}
|
| -
|
| -bool FileInputStream::IsOpen() const {
|
| - return handle_ != INVALID_HANDLE_VALUE;
|
| -}
|
| -
|
| -int64 FileInputStream::Seek(Whence whence, int64 offset) {
|
| - if (!IsOpen())
|
| - return ERR_UNEXPECTED;
|
| - DCHECK(!async_context_.get() || !async_context_->callback());
|
| -
|
| - LARGE_INTEGER distance, result;
|
| - distance.QuadPart = offset;
|
| - DWORD move_method = static_cast<DWORD>(whence);
|
| - if (!SetFilePointerEx(handle_, distance, &result, move_method)) {
|
| - DWORD error = GetLastError();
|
| - LOG(WARNING) << "SetFilePointerEx failed: " << error;
|
| - return MapErrorCode(error);
|
| - }
|
| - if (async_context_.get())
|
| - SetOffset(async_context_->overlapped(), result);
|
| - return result.QuadPart;
|
| -}
|
| -
|
| -int64 FileInputStream::Available() {
|
| - if (!IsOpen())
|
| - return ERR_UNEXPECTED;
|
| -
|
| - int64 cur_pos = Seek(FROM_CURRENT, 0);
|
| - if (cur_pos < 0)
|
| - return cur_pos;
|
| -
|
| - LARGE_INTEGER file_size;
|
| - if (!GetFileSizeEx(handle_, &file_size)) {
|
| - DWORD error = GetLastError();
|
| - LOG(WARNING) << "GetFileSizeEx failed: " << error;
|
| - return MapErrorCode(error);
|
| - }
|
| -
|
| - return file_size.QuadPart - cur_pos;
|
| -}
|
| -
|
| -int FileInputStream::Read(
|
| - char* buf, int buf_len, CompletionCallback* callback) {
|
| - if (!IsOpen())
|
| - return ERR_UNEXPECTED;
|
| -
|
| - OVERLAPPED* overlapped = NULL;
|
| - if (async_context_.get()) {
|
| - DCHECK(!async_context_->callback());
|
| - overlapped = async_context_->overlapped();
|
| - }
|
| -
|
| - int rv;
|
| -
|
| - DWORD bytes_read;
|
| - if (!ReadFile(handle_, buf, buf_len, &bytes_read, overlapped)) {
|
| - DWORD error = GetLastError();
|
| - if (async_context_.get() && error == ERROR_IO_PENDING) {
|
| - async_context_->IOCompletionIsPending(callback);
|
| - rv = ERR_IO_PENDING;
|
| - } else if (error == ERROR_HANDLE_EOF) {
|
| - rv = 0; // Report EOF by returning 0 bytes read.
|
| - } else {
|
| - LOG(WARNING) << "ReadFile failed: " << error;
|
| - rv = MapErrorCode(error);
|
| - }
|
| - } else {
|
| - if (overlapped)
|
| - IncrementOffset(overlapped, bytes_read);
|
| - rv = static_cast<int>(bytes_read);
|
| - }
|
| - return rv;
|
| -}
|
| -
|
| -} // namespace net
|
|
|