// 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 data) { *this = BigBufferView::ToBigBuffer(BigBufferView(data)); } BigBuffer::BigBuffer(const std::vector& 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(const_cast(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_cast(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 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(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 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 BigBufferView::data() const { if (storage_type_ == BigBuffer::StorageType::kBytes) { return bytes_; } else { DCHECK(shared_memory_.has_value()); return base::make_span(static_cast(const_cast( 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