1 // Copyright 2018 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "mojo/public/cpp/base/big_buffer.h" 6 7 #include "base/logging.h" 8 9 namespace mojo_base { 10 11 namespace internal { 12 13 BigBufferSharedMemoryRegion::BigBufferSharedMemoryRegion() = default; 14 15 BigBufferSharedMemoryRegion::BigBufferSharedMemoryRegion( 16 mojo::ScopedSharedBufferHandle buffer_handle, 17 size_t size) 18 : size_(size), 19 buffer_handle_(std::move(buffer_handle)), 20 buffer_mapping_(buffer_handle_->Map(size)) {} 21 22 BigBufferSharedMemoryRegion::BigBufferSharedMemoryRegion( 23 BigBufferSharedMemoryRegion&& other) = default; 24 25 BigBufferSharedMemoryRegion::~BigBufferSharedMemoryRegion() = default; 26 27 BigBufferSharedMemoryRegion& BigBufferSharedMemoryRegion::operator=( 28 BigBufferSharedMemoryRegion&& other) = default; 29 30 mojo::ScopedSharedBufferHandle BigBufferSharedMemoryRegion::TakeBufferHandle() { 31 DCHECK(buffer_handle_.is_valid()); 32 buffer_mapping_.reset(); 33 return std::move(buffer_handle_); 34 } 35 36 } // namespace internal 37 38 // static 39 constexpr size_t BigBuffer::kMaxInlineBytes; 40 41 BigBuffer::BigBuffer() : storage_type_(StorageType::kBytes) {} 42 43 BigBuffer::BigBuffer(BigBuffer&& other) = default; 44 45 BigBuffer::BigBuffer(base::span<const uint8_t> data) { 46 *this = BigBufferView::ToBigBuffer(BigBufferView(data)); 47 } 48 49 BigBuffer::BigBuffer(const std::vector<uint8_t>& data) 50 : BigBuffer(base::make_span(data)) {} 51 52 BigBuffer::BigBuffer(internal::BigBufferSharedMemoryRegion shared_memory) 53 : storage_type_(StorageType::kSharedMemory), 54 shared_memory_(std::move(shared_memory)) {} 55 56 BigBuffer::~BigBuffer() = default; 57 58 BigBuffer& BigBuffer::operator=(BigBuffer&& other) = default; 59 60 uint8_t* BigBuffer::data() { 61 return const_cast<uint8_t*>(const_cast<const BigBuffer*>(this)->data()); 62 } 63 64 const uint8_t* BigBuffer::data() const { 65 switch (storage_type_) { 66 case StorageType::kBytes: 67 return bytes_.data(); 68 case StorageType::kSharedMemory: 69 DCHECK(shared_memory_->buffer_mapping_); 70 return static_cast<const uint8_t*>( 71 const_cast<const void*>(shared_memory_->buffer_mapping_.get())); 72 default: 73 NOTREACHED(); 74 return nullptr; 75 } 76 } 77 78 size_t BigBuffer::size() const { 79 switch (storage_type_) { 80 case StorageType::kBytes: 81 return bytes_.size(); 82 case StorageType::kSharedMemory: 83 return shared_memory_->size(); 84 default: 85 NOTREACHED(); 86 return 0; 87 } 88 } 89 90 BigBufferView::BigBufferView() = default; 91 92 BigBufferView::BigBufferView(BigBufferView&& other) = default; 93 94 BigBufferView::BigBufferView(base::span<const uint8_t> bytes) { 95 if (bytes.size() > BigBuffer::kMaxInlineBytes) { 96 auto buffer = mojo::SharedBufferHandle::Create(bytes.size()); 97 if (buffer.is_valid()) { 98 storage_type_ = BigBuffer::StorageType::kSharedMemory; 99 shared_memory_.emplace(std::move(buffer), bytes.size()); 100 std::copy(bytes.begin(), bytes.end(), 101 static_cast<uint8_t*>(shared_memory_->buffer_mapping_.get())); 102 return; 103 } 104 } 105 106 // Either the data is small enough or shared memory allocation failed. Either 107 // way we fall back to directly referencing the input bytes. 108 storage_type_ = BigBuffer::StorageType::kBytes; 109 bytes_ = bytes; 110 } 111 112 BigBufferView::~BigBufferView() = default; 113 114 BigBufferView& BigBufferView::operator=(BigBufferView&& other) = default; 115 116 void BigBufferView::SetBytes(base::span<const uint8_t> bytes) { 117 DCHECK(bytes_.empty()); 118 DCHECK(!shared_memory_); 119 storage_type_ = BigBuffer::StorageType::kBytes; 120 bytes_ = bytes; 121 } 122 123 void BigBufferView::SetSharedMemory( 124 internal::BigBufferSharedMemoryRegion shared_memory) { 125 DCHECK(bytes_.empty()); 126 DCHECK(!shared_memory_); 127 storage_type_ = BigBuffer::StorageType::kSharedMemory; 128 shared_memory_ = std::move(shared_memory); 129 } 130 131 base::span<const uint8_t> BigBufferView::data() const { 132 if (storage_type_ == BigBuffer::StorageType::kBytes) { 133 return bytes_; 134 } else { 135 DCHECK(shared_memory_.has_value()); 136 return base::make_span(static_cast<const uint8_t*>(const_cast<const void*>( 137 shared_memory_->memory())), 138 shared_memory_->size()); 139 } 140 } 141 142 // static 143 BigBuffer BigBufferView::ToBigBuffer(BigBufferView view) { 144 BigBuffer buffer; 145 buffer.storage_type_ = view.storage_type_; 146 if (view.storage_type_ == BigBuffer::StorageType::kBytes) { 147 std::copy(view.bytes_.begin(), view.bytes_.end(), 148 std::back_inserter(buffer.bytes_)); 149 } else { 150 buffer.shared_memory_ = std::move(*view.shared_memory_); 151 } 152 return buffer; 153 } 154 155 } // namespace mojo_base 156