• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
BigBufferSharedMemoryRegion(mojo::ScopedSharedBufferHandle buffer_handle,size_t size)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 
TakeBufferHandle()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 
BigBuffer()41 BigBuffer::BigBuffer() : storage_type_(StorageType::kBytes) {}
42 
43 BigBuffer::BigBuffer(BigBuffer&& other) = default;
44 
BigBuffer(base::span<const uint8_t> data)45 BigBuffer::BigBuffer(base::span<const uint8_t> data) {
46   *this = BigBufferView::ToBigBuffer(BigBufferView(data));
47 }
48 
BigBuffer(const std::vector<uint8_t> & data)49 BigBuffer::BigBuffer(const std::vector<uint8_t>& data)
50     : BigBuffer(base::make_span(data)) {}
51 
BigBuffer(internal::BigBufferSharedMemoryRegion shared_memory)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 
data()60 uint8_t* BigBuffer::data() {
61   return const_cast<uint8_t*>(const_cast<const BigBuffer*>(this)->data());
62 }
63 
data() const64 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 
size() const78 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 
BigBufferView(base::span<const uint8_t> bytes)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 
SetBytes(base::span<const uint8_t> bytes)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 
SetSharedMemory(internal::BigBufferSharedMemoryRegion shared_memory)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 
data() const131 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
ToBigBuffer(BigBufferView view)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