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