普通文本  |  79行  |  2.03 KB

// 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