1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef NOGROD_BUFFER_
18 #define NOGROD_BUFFER_
19 
20 #include <cstddef>
21 #include <vector>
22 
23 namespace nogrod {
24 
25 // This class represents a buffer which might optionally
26 // be backed by std::vector<T> and therefore is move-only.
27 template <typename T>
28 class Buffer {
29  public:
30   Buffer() = default;
Buffer(std::vector<T> buffer)31   explicit Buffer(std::vector<T> buffer)
32       : buffer_{std::move(buffer)}, data_{buffer_.data()}, size_{buffer_.size()} {}
Buffer(const T * data,size_t size)33   explicit constexpr Buffer(const T* data, size_t size) : data_{data}, size_{size} {}
34 
data()35   constexpr const T* data() const { return data_; }
size()36   constexpr size_t size() const { return size_; }
37 
38   // Move-only
39   Buffer(const Buffer<T>&) = delete;
40   Buffer<T>& operator=(const Buffer<T>&) = delete;
41 
42   // Since I haven't found a written guarantee that std::vector move
43   // preserves the data pointer we cannot rely on default move here.
Buffer(Buffer<T> && that)44   Buffer(Buffer<T>&& that) { *this = std::move(that); }
45 
46   Buffer<T>& operator=(Buffer<T>&& that) {
47     bool that_data_points_to_vector = (that.data_ == that.buffer_.data());
48     this->buffer_ = std::move(that.buffer_);
49     if (that_data_points_to_vector) {
50       this->data_ = this->buffer_.data();
51     } else {
52       this->data_ = that.data_;
53     }
54     this->size_ = that.size_;
55 
56     return *this;
57   }
58 
59  private:
60   std::vector<T> buffer_;
61   const T* data_;
62   size_t size_;
63 };
64 
65 }  // namespace nogrod
66 
67 #endif  // NOGROD_BUFFER_