Make Buffered{Source,Sink} move-safe

This commit is contained in:
Shea Levy 2016-07-13 06:03:37 -04:00
parent cb5e7254b6
commit b33e85229d
2 changed files with 12 additions and 27 deletions

View File

@ -8,18 +8,9 @@
namespace nix { namespace nix {
BufferedSink::~BufferedSink()
{
/* We can't call flush() here, because C++ for some insane reason
doesn't allow you to call virtual methods from a destructor. */
assert(!bufPos);
delete[] buffer;
}
void BufferedSink::operator () (const unsigned char * data, size_t len) void BufferedSink::operator () (const unsigned char * data, size_t len)
{ {
if (!buffer) buffer = new unsigned char[bufSize]; if (!buffer) buffer = decltype(buffer)(new unsigned char[bufSize]);
while (len) { while (len) {
/* Optimisation: bypass the buffer if the data exceeds the /* Optimisation: bypass the buffer if the data exceeds the
@ -32,7 +23,7 @@ void BufferedSink::operator () (const unsigned char * data, size_t len)
/* Otherwise, copy the bytes to the buffer. Flush the buffer /* Otherwise, copy the bytes to the buffer. Flush the buffer
when it's full. */ when it's full. */
size_t n = bufPos + len > bufSize ? bufSize - bufPos : len; size_t n = bufPos + len > bufSize ? bufSize - bufPos : len;
memcpy(buffer + bufPos, data, n); memcpy(buffer.get() + bufPos, data, n);
data += n; bufPos += n; len -= n; data += n; bufPos += n; len -= n;
if (bufPos == bufSize) flush(); if (bufPos == bufSize) flush();
} }
@ -44,7 +35,7 @@ void BufferedSink::flush()
if (bufPos == 0) return; if (bufPos == 0) return;
size_t n = bufPos; size_t n = bufPos;
bufPos = 0; // don't trigger the assert() in ~BufferedSink() bufPos = 0; // don't trigger the assert() in ~BufferedSink()
write(buffer, n); write(buffer.get(), n);
} }
@ -95,21 +86,15 @@ void Source::operator () (unsigned char * data, size_t len)
} }
BufferedSource::~BufferedSource()
{
delete[] buffer;
}
size_t BufferedSource::read(unsigned char * data, size_t len) size_t BufferedSource::read(unsigned char * data, size_t len)
{ {
if (!buffer) buffer = new unsigned char[bufSize]; if (!buffer) buffer = decltype(buffer)(new unsigned char[bufSize]);
if (!bufPosIn) bufPosIn = readUnbuffered(buffer, bufSize); if (!bufPosIn) bufPosIn = readUnbuffered(buffer.get(), bufSize);
/* Copy out the data in the buffer. */ /* Copy out the data in the buffer. */
size_t n = len > bufPosIn - bufPosOut ? bufPosIn - bufPosOut : len; size_t n = len > bufPosIn - bufPosOut ? bufPosIn - bufPosOut : len;
memcpy(data, buffer + bufPosOut, n); memcpy(data, buffer.get() + bufPosOut, n);
bufPosOut += n; bufPosOut += n;
if (bufPosIn == bufPosOut) bufPosIn = bufPosOut = 0; if (bufPosIn == bufPosOut) bufPosIn = bufPosOut = 0;
return n; return n;

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <memory>
#include "types.hh" #include "types.hh"
#include "util.hh" #include "util.hh"
@ -25,11 +27,10 @@ struct Sink
struct BufferedSink : Sink struct BufferedSink : Sink
{ {
size_t bufSize, bufPos; size_t bufSize, bufPos;
unsigned char * buffer; std::unique_ptr<unsigned char[]> buffer;
BufferedSink(size_t bufSize = 32 * 1024) BufferedSink(size_t bufSize = 32 * 1024)
: bufSize(bufSize), bufPos(0), buffer(0) { } : bufSize(bufSize), bufPos(0), buffer(nullptr) { }
~BufferedSink();
void operator () (const unsigned char * data, size_t len) override; void operator () (const unsigned char * data, size_t len) override;
@ -67,11 +68,10 @@ struct Source
struct BufferedSource : Source struct BufferedSource : Source
{ {
size_t bufSize, bufPosIn, bufPosOut; size_t bufSize, bufPosIn, bufPosOut;
unsigned char * buffer; std::unique_ptr<unsigned char[]> buffer;
BufferedSource(size_t bufSize = 32 * 1024) BufferedSource(size_t bufSize = 32 * 1024)
: bufSize(bufSize), bufPosIn(0), bufPosOut(0), buffer(0) { } : bufSize(bufSize), bufPosIn(0), bufPosOut(0), buffer(nullptr) { }
~BufferedSource();
size_t read(unsigned char * data, size_t len) override; size_t read(unsigned char * data, size_t len) override;