1 #ifndef QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_MEM_SLICE_IMPL_H_
2 #define QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_MEM_SLICE_IMPL_H_
3 
4 #include <cstddef>
5 #include <cstdlib>
6 #include <memory>
7 #include <utility>
8 
9 #include "quiche/common/platform/api/quiche_export.h"
10 #include "quiche/common/quiche_buffer_allocator.h"
11 #include "quiche/common/quiche_callbacks.h"
12 
13 namespace quiche {
14 
15 class QUICHE_EXPORT QuicheMemSliceImpl {
16  public:
17   QuicheMemSliceImpl() = default;
18 
QuicheMemSliceImpl(QuicheBuffer buffer)19   explicit QuicheMemSliceImpl(QuicheBuffer buffer)
20       : data_(buffer.data()), size_(buffer.size()) {
21     QuicheUniqueBufferPtr owned = buffer.Release();
22     QuicheBufferAllocator* allocator = owned.get_deleter().allocator();
23     owned.release();
24     done_callback_ = [allocator](const char* ptr) {
25       allocator->Delete(const_cast<char*>(ptr));
26     };
27   }
28 
QuicheMemSliceImpl(std::unique_ptr<char[]> buffer,size_t length)29   QuicheMemSliceImpl(std::unique_ptr<char[]> buffer, size_t length)
30       : data_(buffer.release()),
31         size_(length),
32         done_callback_(+[](const char* ptr) { delete[] ptr; }) {}
33 
QuicheMemSliceImpl(const char * buffer,size_t length,SingleUseCallback<void (const char *)> done_callback)34   QuicheMemSliceImpl(const char* buffer, size_t length,
35                      SingleUseCallback<void(const char*)> done_callback)
36       : data_(buffer),
37         size_(length),
38         done_callback_(std::move(done_callback)) {}
39 
40   QuicheMemSliceImpl(const QuicheMemSliceImpl& other) = delete;
41   QuicheMemSliceImpl& operator=(const QuicheMemSliceImpl& other) = delete;
42 
43   // Move constructors. |other| will not hold a reference to the data buffer
44   // after this call completes.
QuicheMemSliceImpl(QuicheMemSliceImpl && other)45   QuicheMemSliceImpl(QuicheMemSliceImpl&& other) {
46     data_ = other.data_;
47     size_ = other.size_;
48     done_callback_ = std::move(other.done_callback_);
49     other.data_ = nullptr;
50     other.size_ = 0;
51     other.done_callback_ = nullptr;
52   }
53   QuicheMemSliceImpl& operator=(QuicheMemSliceImpl&& other) {
54     Reset();
55     data_ = other.data_;
56     size_ = other.size_;
57     done_callback_ = std::move(other.done_callback_);
58     other.data_ = nullptr;
59     other.size_ = 0;
60     other.done_callback_ = nullptr;
61     return *this;
62   }
63 
~QuicheMemSliceImpl()64   ~QuicheMemSliceImpl() { Reset(); }
65 
Reset()66   void Reset() {
67     if (done_callback_ && data_ != nullptr) {
68       std::move(done_callback_)(data_);
69     }
70     data_ = nullptr;
71     size_ = 0;
72     done_callback_ = nullptr;
73   }
74 
data()75   const char* data() const { return data_; }
length()76   size_t length() const { return size_; }
empty()77   bool empty() const { return size_ == 0; }
78 
79  private:
80   const char* data_;
81   size_t size_;
82   SingleUseCallback<void(const char*)> done_callback_;
83 };
84 
85 }  // namespace quiche
86 
87 #endif  // QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_MEM_SLICE_IMPL_H_
88