Home | History | Annotate | Download | only in base
      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