blob: aefda0a1141206e329caaa5075b5b445515c79a5 [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/paint_preview/common/file_stream.h"
#include <stdint.h>
#include <utility>
#include "base/compiler_specific.h"
namespace paint_preview {
namespace {
bool ShouldWrite(size_t current_size, size_t max_size, size_t added_size) {
// If |current_size| + |added_size| overflow then don't write.
if (std::numeric_limits<size_t>::max() - current_size < added_size)
return false;
return max_size >= current_size + added_size;
}
} // namespace
// FileWStream
FileWStream::FileWStream(base::File file)
: file_(std::move(file)),
max_size_(0),
bytes_written_(0),
fake_bytes_written_(0),
has_write_failed_(false) {
DCHECK(file_.IsValid());
}
FileWStream::FileWStream(base::File file, size_t max_size)
: file_(std::move(file)),
max_size_(max_size),
bytes_written_(0),
fake_bytes_written_(0),
has_write_failed_(false) {
DCHECK(file_.IsValid());
}
// Close() is called in the destructor of |file_|.
FileWStream::~FileWStream() = default;
bool FileWStream::write(const void* buffer, size_t size) {
fake_bytes_written_ += size;
if (!file_.IsValid() || has_write_failed_)
return false;
if (max_size_ && !ShouldWrite(bytes_written_, max_size_, size)) {
has_write_failed_ = true;
return false;
}
int bytes = UNSAFE_TODO(
file_.WriteAtCurrentPos(reinterpret_cast<const char*>(buffer), size));
if (bytes < 0) {
has_write_failed_ = true;
return false;
}
bytes_written_ += bytes;
if (static_cast<size_t>(bytes) != size) {
has_write_failed_ = true;
return false;
}
return true;
}
void FileWStream::flush() {
if (!file_.IsValid())
return;
file_.Flush();
}
size_t FileWStream::bytesWritten() const {
return fake_bytes_written_;
}
void FileWStream::Close() {
if (!file_.IsValid())
return;
file_.Close();
}
// FileRStream
FileRStream::FileRStream(base::File file)
: file_(std::move(file)), length_(file_.GetLength()), bytes_read_(0) {
DCHECK(file_.IsValid());
}
FileRStream::~FileRStream() = default;
size_t FileRStream::read(void* buffer, size_t size) {
if (!file_.IsValid())
return 0;
int64_t num_bytes;
if (!buffer) {
int64_t origin = file_.Seek(base::File::FROM_CURRENT, 0);
if (origin < 0)
return 0;
num_bytes = file_.Seek(base::File::FROM_CURRENT, size);
if (num_bytes < 0)
return 0;
num_bytes = num_bytes - origin;
} else {
num_bytes = UNSAFE_TODO(
file_.ReadAtCurrentPos(reinterpret_cast<char*>(buffer), size));
}
if (num_bytes < 0)
return 0;
bytes_read_ += num_bytes;
return num_bytes;
}
bool FileRStream::isAtEnd() const {
return bytes_read_ == length_;
}
bool FileRStream::hasLength() const {
return true;
}
size_t FileRStream::getLength() const {
return length_;
}
} // namespace paint_preview