100 lines
2.6 KiB
C
100 lines
2.6 KiB
C
|
/*
|
||
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* This source code is licensed under both the BSD-style license (found in the
|
||
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
||
|
* in the COPYING file in the root directory of this source tree).
|
||
|
*/
|
||
|
#pragma once
|
||
|
|
||
|
#include "utils/Range.h"
|
||
|
|
||
|
#include <array>
|
||
|
#include <cstddef>
|
||
|
#include <memory>
|
||
|
|
||
|
namespace pzstd {
|
||
|
|
||
|
/**
|
||
|
* A `Buffer` has a pointer to a shared buffer, and a range of the buffer that
|
||
|
* it owns.
|
||
|
* The idea is that you can allocate one buffer, and write chunks into it
|
||
|
* and break off those chunks.
|
||
|
* The underlying buffer is reference counted, and will be destroyed when all
|
||
|
* `Buffer`s that reference it are destroyed.
|
||
|
*/
|
||
|
class Buffer {
|
||
|
std::shared_ptr<unsigned char> buffer_;
|
||
|
MutableByteRange range_;
|
||
|
|
||
|
static void delete_buffer(unsigned char* buffer) {
|
||
|
delete[] buffer;
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
/// Construct an empty buffer that owns no data.
|
||
|
explicit Buffer() {}
|
||
|
|
||
|
/// Construct a `Buffer` that owns a new underlying buffer of size `size`.
|
||
|
explicit Buffer(std::size_t size)
|
||
|
: buffer_(new unsigned char[size], delete_buffer),
|
||
|
range_(buffer_.get(), buffer_.get() + size) {}
|
||
|
|
||
|
explicit Buffer(std::shared_ptr<unsigned char> buffer, MutableByteRange data)
|
||
|
: buffer_(buffer), range_(data) {}
|
||
|
|
||
|
Buffer(Buffer&&) = default;
|
||
|
Buffer& operator=(Buffer&&) = default;
|
||
|
|
||
|
/**
|
||
|
* Splits the data into two pieces: [begin, begin + n), [begin + n, end).
|
||
|
* Their data both points into the same underlying buffer.
|
||
|
* Modifies the original `Buffer` to point to only [begin + n, end).
|
||
|
*
|
||
|
* @param n The offset to split at.
|
||
|
* @returns A buffer that owns the data [begin, begin + n).
|
||
|
*/
|
||
|
Buffer splitAt(std::size_t n) {
|
||
|
auto firstPiece = range_.subpiece(0, n);
|
||
|
range_.advance(n);
|
||
|
return Buffer(buffer_, firstPiece);
|
||
|
}
|
||
|
|
||
|
/// Modifies the buffer to point to the range [begin + n, end).
|
||
|
void advance(std::size_t n) {
|
||
|
range_.advance(n);
|
||
|
}
|
||
|
|
||
|
/// Modifies the buffer to point to the range [begin, end - n).
|
||
|
void subtract(std::size_t n) {
|
||
|
range_.subtract(n);
|
||
|
}
|
||
|
|
||
|
/// Returns a read only `Range` pointing to the `Buffer`s data.
|
||
|
ByteRange range() const {
|
||
|
return range_;
|
||
|
}
|
||
|
/// Returns a mutable `Range` pointing to the `Buffer`s data.
|
||
|
MutableByteRange range() {
|
||
|
return range_;
|
||
|
}
|
||
|
|
||
|
const unsigned char* data() const {
|
||
|
return range_.data();
|
||
|
}
|
||
|
|
||
|
unsigned char* data() {
|
||
|
return range_.data();
|
||
|
}
|
||
|
|
||
|
std::size_t size() const {
|
||
|
return range_.size();
|
||
|
}
|
||
|
|
||
|
bool empty() const {
|
||
|
return range_.empty();
|
||
|
}
|
||
|
};
|
||
|
}
|