1 /* 2 * Copyright (c) 2016-present, Facebook, Inc. 3 * All rights reserved. 4 * 5 * This source code is licensed under both the BSD-style license (found in the 6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found 7 * in the COPYING file in the root directory of this source tree). 8 */ 9 #pragma once 10 11 #include "utils/Range.h" 12 13 #include <array> 14 #include <cstddef> 15 #include <memory> 16 17 namespace pzstd { 18 19 /** 20 * A `Buffer` has a pointer to a shared buffer, and a range of the buffer that 21 * it owns. 22 * The idea is that you can allocate one buffer, and write chunks into it 23 * and break off those chunks. 24 * The underlying buffer is reference counted, and will be destroyed when all 25 * `Buffer`s that reference it are destroyed. 26 */ 27 class Buffer { 28 std::shared_ptr<unsigned char> buffer_; 29 MutableByteRange range_; 30 delete_buffer(unsigned char * buffer)31 static void delete_buffer(unsigned char* buffer) { 32 delete[] buffer; 33 } 34 35 public: 36 /// Construct an empty buffer that owns no data. Buffer()37 explicit Buffer() {} 38 39 /// Construct a `Buffer` that owns a new underlying buffer of size `size`. Buffer(std::size_t size)40 explicit Buffer(std::size_t size) 41 : buffer_(new unsigned char[size], delete_buffer), 42 range_(buffer_.get(), buffer_.get() + size) {} 43 Buffer(std::shared_ptr<unsigned char> buffer,MutableByteRange data)44 explicit Buffer(std::shared_ptr<unsigned char> buffer, MutableByteRange data) 45 : buffer_(buffer), range_(data) {} 46 47 Buffer(Buffer&&) = default; 48 Buffer& operator=(Buffer&&) & = default; 49 50 /** 51 * Splits the data into two pieces: [begin, begin + n), [begin + n, end). 52 * Their data both points into the same underlying buffer. 53 * Modifies the original `Buffer` to point to only [begin + n, end). 54 * 55 * @param n The offset to split at. 56 * @returns A buffer that owns the data [begin, begin + n). 57 */ splitAt(std::size_t n)58 Buffer splitAt(std::size_t n) { 59 auto firstPiece = range_.subpiece(0, n); 60 range_.advance(n); 61 return Buffer(buffer_, firstPiece); 62 } 63 64 /// Modifies the buffer to point to the range [begin + n, end). advance(std::size_t n)65 void advance(std::size_t n) { 66 range_.advance(n); 67 } 68 69 /// Modifies the buffer to point to the range [begin, end - n). subtract(std::size_t n)70 void subtract(std::size_t n) { 71 range_.subtract(n); 72 } 73 74 /// Returns a read only `Range` pointing to the `Buffer`s data. range()75 ByteRange range() const { 76 return range_; 77 } 78 /// Returns a mutable `Range` pointing to the `Buffer`s data. range()79 MutableByteRange range() { 80 return range_; 81 } 82 data()83 const unsigned char* data() const { 84 return range_.data(); 85 } 86 data()87 unsigned char* data() { 88 return range_.data(); 89 } 90 size()91 std::size_t size() const { 92 return range_.size(); 93 } 94 empty()95 bool empty() const { 96 return range_.empty(); 97 } 98 }; 99 } 100