You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
4.6 KiB
156 lines
4.6 KiB
// Copyright 2018 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 "mojo/public/cpp/base/big_buffer.h"
|
|
|
|
#include "base/logging.h"
|
|
|
|
namespace mojo_base {
|
|
|
|
namespace internal {
|
|
|
|
BigBufferSharedMemoryRegion::BigBufferSharedMemoryRegion() = default;
|
|
|
|
BigBufferSharedMemoryRegion::BigBufferSharedMemoryRegion(
|
|
mojo::ScopedSharedBufferHandle buffer_handle,
|
|
size_t size)
|
|
: size_(size),
|
|
buffer_handle_(std::move(buffer_handle)),
|
|
buffer_mapping_(buffer_handle_->Map(size)) {}
|
|
|
|
BigBufferSharedMemoryRegion::BigBufferSharedMemoryRegion(
|
|
BigBufferSharedMemoryRegion&& other) = default;
|
|
|
|
BigBufferSharedMemoryRegion::~BigBufferSharedMemoryRegion() = default;
|
|
|
|
BigBufferSharedMemoryRegion& BigBufferSharedMemoryRegion::operator=(
|
|
BigBufferSharedMemoryRegion&& other) = default;
|
|
|
|
mojo::ScopedSharedBufferHandle BigBufferSharedMemoryRegion::TakeBufferHandle() {
|
|
DCHECK(buffer_handle_.is_valid());
|
|
buffer_mapping_.reset();
|
|
return std::move(buffer_handle_);
|
|
}
|
|
|
|
} // namespace internal
|
|
|
|
// static
|
|
constexpr size_t BigBuffer::kMaxInlineBytes;
|
|
|
|
BigBuffer::BigBuffer() : storage_type_(StorageType::kBytes) {}
|
|
|
|
BigBuffer::BigBuffer(BigBuffer&& other) = default;
|
|
|
|
BigBuffer::BigBuffer(base::span<const uint8_t> data) {
|
|
*this = BigBufferView::ToBigBuffer(BigBufferView(data));
|
|
}
|
|
|
|
BigBuffer::BigBuffer(const std::vector<uint8_t>& data)
|
|
: BigBuffer(base::make_span(data)) {}
|
|
|
|
BigBuffer::BigBuffer(internal::BigBufferSharedMemoryRegion shared_memory)
|
|
: storage_type_(StorageType::kSharedMemory),
|
|
shared_memory_(std::move(shared_memory)) {}
|
|
|
|
BigBuffer::~BigBuffer() = default;
|
|
|
|
BigBuffer& BigBuffer::operator=(BigBuffer&& other) = default;
|
|
|
|
uint8_t* BigBuffer::data() {
|
|
return const_cast<uint8_t*>(const_cast<const BigBuffer*>(this)->data());
|
|
}
|
|
|
|
const uint8_t* BigBuffer::data() const {
|
|
switch (storage_type_) {
|
|
case StorageType::kBytes:
|
|
return bytes_.data();
|
|
case StorageType::kSharedMemory:
|
|
DCHECK(shared_memory_->buffer_mapping_);
|
|
return static_cast<const uint8_t*>(
|
|
const_cast<const void*>(shared_memory_->buffer_mapping_.get()));
|
|
default:
|
|
NOTREACHED();
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
size_t BigBuffer::size() const {
|
|
switch (storage_type_) {
|
|
case StorageType::kBytes:
|
|
return bytes_.size();
|
|
case StorageType::kSharedMemory:
|
|
return shared_memory_->size();
|
|
default:
|
|
NOTREACHED();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
BigBufferView::BigBufferView() = default;
|
|
|
|
BigBufferView::BigBufferView(BigBufferView&& other) = default;
|
|
|
|
BigBufferView::BigBufferView(base::span<const uint8_t> bytes) {
|
|
if (bytes.size() > BigBuffer::kMaxInlineBytes) {
|
|
auto buffer = mojo::SharedBufferHandle::Create(bytes.size());
|
|
if (buffer.is_valid()) {
|
|
storage_type_ = BigBuffer::StorageType::kSharedMemory;
|
|
shared_memory_.emplace(std::move(buffer), bytes.size());
|
|
std::copy(bytes.begin(), bytes.end(),
|
|
static_cast<uint8_t*>(shared_memory_->buffer_mapping_.get()));
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Either the data is small enough or shared memory allocation failed. Either
|
|
// way we fall back to directly referencing the input bytes.
|
|
storage_type_ = BigBuffer::StorageType::kBytes;
|
|
bytes_ = bytes;
|
|
}
|
|
|
|
BigBufferView::~BigBufferView() = default;
|
|
|
|
BigBufferView& BigBufferView::operator=(BigBufferView&& other) = default;
|
|
|
|
void BigBufferView::SetBytes(base::span<const uint8_t> bytes) {
|
|
DCHECK(bytes_.empty());
|
|
DCHECK(!shared_memory_);
|
|
storage_type_ = BigBuffer::StorageType::kBytes;
|
|
bytes_ = bytes;
|
|
}
|
|
|
|
void BigBufferView::SetSharedMemory(
|
|
internal::BigBufferSharedMemoryRegion shared_memory) {
|
|
DCHECK(bytes_.empty());
|
|
DCHECK(!shared_memory_);
|
|
storage_type_ = BigBuffer::StorageType::kSharedMemory;
|
|
shared_memory_ = std::move(shared_memory);
|
|
}
|
|
|
|
base::span<const uint8_t> BigBufferView::data() const {
|
|
if (storage_type_ == BigBuffer::StorageType::kBytes) {
|
|
return bytes_;
|
|
} else {
|
|
DCHECK(shared_memory_.has_value());
|
|
return base::make_span(static_cast<const uint8_t*>(const_cast<const void*>(
|
|
shared_memory_->memory())),
|
|
shared_memory_->size());
|
|
}
|
|
}
|
|
|
|
// static
|
|
BigBuffer BigBufferView::ToBigBuffer(BigBufferView view) {
|
|
BigBuffer buffer;
|
|
buffer.storage_type_ = view.storage_type_;
|
|
if (view.storage_type_ == BigBuffer::StorageType::kBytes) {
|
|
std::copy(view.bytes_.begin(), view.bytes_.end(),
|
|
std::back_inserter(buffer.bytes_));
|
|
} else {
|
|
buffer.shared_memory_ = std::move(*view.shared_memory_);
|
|
}
|
|
return buffer;
|
|
}
|
|
|
|
} // namespace mojo_base
|