// Copyright 2017 The Chromium OS 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 "puffin/src/memory_stream.h"
#include <fcntl.h>
#include <unistd.h>
#include <algorithm>
#include <utility>
#include "puffin/src/include/puffin/common.h"
#include "puffin/src/set_errors.h"
namespace puffin {
UniqueStreamPtr MemoryStream::CreateForRead(const Buffer& memory) {
return UniqueStreamPtr(new MemoryStream(&memory, nullptr));
}
UniqueStreamPtr MemoryStream::CreateForWrite(Buffer* memory) {
return UniqueStreamPtr(new MemoryStream(nullptr, memory));
}
MemoryStream::MemoryStream(const Buffer* read_memory, Buffer* write_memory)
: read_memory_(read_memory),
write_memory_(write_memory),
offset_(0),
open_(true) {}
bool MemoryStream::GetSize(uint64_t* size) const {
*size =
read_memory_ != nullptr ? read_memory_->size() : write_memory_->size();
return true;
}
bool MemoryStream::GetOffset(uint64_t* offset) const {
*offset = offset_;
return true;
}
bool MemoryStream::Seek(uint64_t offset) {
TEST_AND_RETURN_FALSE(open_);
uint64_t size;
GetSize(&size);
TEST_AND_RETURN_FALSE(offset <= size);
offset_ = offset;
return true;
}
bool MemoryStream::Read(void* buffer, size_t length) {
TEST_AND_RETURN_FALSE(open_);
TEST_AND_RETURN_FALSE(read_memory_ != nullptr);
TEST_AND_RETURN_FALSE(offset_ + length <= read_memory_->size());
memcpy(buffer, read_memory_->data() + offset_, length);
offset_ += length;
return true;
}
bool MemoryStream::Write(const void* buffer, size_t length) {
// TODO(ahassani): Add a maximum size limit to prevent malicious attacks.
TEST_AND_RETURN_FALSE(open_);
TEST_AND_RETURN_FALSE(write_memory_ != nullptr);
if (offset_ + length > write_memory_->size()) {
write_memory_->resize(offset_ + length);
}
memcpy(write_memory_->data() + offset_, buffer, length);
offset_ += length;
return true;
}
bool MemoryStream::Close() {
open_ = false;
return true;
}
} // namespace puffin