Allow byte_stream->byte_slice conversion to shrink unused buffer space

This commit is contained in:
Lee Clagett 2020-10-13 15:09:18 +00:00
parent 83f1d863bd
commit 249eae5f4a
3 changed files with 24 additions and 6 deletions

View file

@ -112,7 +112,7 @@ namespace epee
explicit byte_slice(std::string&& buffer); explicit byte_slice(std::string&& buffer);
//! Convert `stream` into a slice with zero allocations. //! Convert `stream` into a slice with zero allocations.
explicit byte_slice(byte_stream&& stream) noexcept; explicit byte_slice(byte_stream&& stream, bool shrink = true);
byte_slice(byte_slice&& source) noexcept; byte_slice(byte_slice&& source) noexcept;
~byte_slice() noexcept = default; ~byte_slice() noexcept = default;

View file

@ -36,6 +36,11 @@
#include "byte_slice.h" #include "byte_slice.h"
#include "byte_stream.h" #include "byte_stream.h"
namespace
{
const std::size_t page_size = 4096;
}
namespace epee namespace epee
{ {
struct byte_slice_data struct byte_slice_data
@ -173,16 +178,27 @@ namespace epee
: byte_slice(adapt_buffer{}, std::move(buffer)) : byte_slice(adapt_buffer{}, std::move(buffer))
{} {}
byte_slice::byte_slice(byte_stream&& stream) noexcept byte_slice::byte_slice(byte_stream&& stream, const bool shrink)
: storage_(nullptr), portion_(stream.data(), stream.size()) : storage_(nullptr), portion_(stream.data(), stream.size())
{ {
if (stream.size()) if (portion_.size())
{ {
std::uint8_t* const data = stream.take_buffer().release() - sizeof(raw_byte_slice); byte_buffer buf;
if (shrink && page_size <= stream.available())
{
buf = byte_buffer_resize(stream.take_buffer(), portion_.size());
if (!buf)
throw std::bad_alloc{};
portion_ = {buf.get(), portion_.size()};
}
else // no need to shrink buffer
buf = stream.take_buffer();
std::uint8_t* const data = buf.release() - sizeof(raw_byte_slice);
new (data) raw_byte_slice{}; new (data) raw_byte_slice{};
storage_.reset(reinterpret_cast<raw_byte_slice*>(data)); storage_.reset(reinterpret_cast<raw_byte_slice*>(data));
} }
else else // empty stream
portion_ = nullptr; portion_ = nullptr;
} }

View file

@ -1090,11 +1090,13 @@ TEST(ByteStream, ToByteSlice)
epee::byte_stream stream; epee::byte_stream stream;
stream.reserve(128*1024);
stream.write(source); stream.write(source);
EXPECT_EQ(sizeof(source), stream.size()); EXPECT_EQ(sizeof(source), stream.size());
EXPECT_EQ(128*1024, stream.capacity());
EXPECT_TRUE(equal(source, byte_span{stream.data(), stream.size()})); EXPECT_TRUE(equal(source, byte_span{stream.data(), stream.size()}));
const epee::byte_slice slice{std::move(stream)}; const epee::byte_slice slice{std::move(stream), true};
EXPECT_EQ(0u, stream.size()); EXPECT_EQ(0u, stream.size());
EXPECT_EQ(0u, stream.available()); EXPECT_EQ(0u, stream.available());
EXPECT_EQ(0u, stream.capacity()); EXPECT_EQ(0u, stream.capacity());