First
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
#include "StdAfx.h"
|
||||
#include "fs/CopyStream.h"
|
||||
#include "fs/IStreamSink.h"
|
||||
#include "fs/IStreamSource.h"
|
||||
#include <tl/functional.h>
|
||||
|
||||
#include "fs/IFilesystem.h"
|
||||
|
||||
namespace fs
|
||||
{
|
||||
|
||||
static constexpr size_t k_defaultBufferSize = 100 * 1024;
|
||||
|
||||
CopyStreamResult copyStream(IStreamSink& sink, IStreamSource& source, size_t bufferSize)
|
||||
{
|
||||
return copyStream(sink, source, nullptr, bufferSize);
|
||||
}
|
||||
|
||||
CopyStreamResult copyStream(IStreamSink& sink, IStreamSource& source, const ProcessDataCallback& dataCallback, size_t bufferSize)
|
||||
{
|
||||
if (bufferSize == 0)
|
||||
bufferSize = source.getPreferredBufferSize();
|
||||
|
||||
if (bufferSize == 0)
|
||||
bufferSize = sink.getPreferredBufferSize();
|
||||
|
||||
if (bufferSize == 0)
|
||||
bufferSize = k_defaultBufferSize;
|
||||
|
||||
tl::memory_buffer buffer;
|
||||
buffer.resize_uninitialized(bufferSize);
|
||||
|
||||
uint64_t size = 0;
|
||||
do
|
||||
{
|
||||
const uint64_t read = source.read(buffer);
|
||||
tl::optional<Error> optLastError = source.getLastError();
|
||||
if (optLastError.has_value())
|
||||
return *optLastError;
|
||||
|
||||
if (read == 0)
|
||||
return size;
|
||||
|
||||
if (dataCallback)
|
||||
dataCallback({ buffer.data(), static_cast<size_t>(read) });
|
||||
|
||||
const uint64_t written = sink.write({ buffer.data(), static_cast<size_t>(read) });
|
||||
if (written != read)
|
||||
return tl::make_error<Error>(ErrorCode::SystemError, "Failed to write {} bytes. Only {} went through", read, written);
|
||||
|
||||
size += written;
|
||||
|
||||
optLastError = sink.getLastError();
|
||||
if (optLastError.has_value())
|
||||
return *optLastError;
|
||||
} while (!source.isEOS());
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CopyStreamResult copyFile(IStreamSink& sink, const IFilesystem& filesystem, const AbsPath& filePath, size_t bufferSize)
|
||||
{
|
||||
OUTCOME_TRY(const auto source, filesystem.openStreamSource(filePath, IFilesystem::SourceFlags(IFilesystem::SourceFlag::SequentialHint, IFilesystem::SourceFlag::Unbuffered)));
|
||||
return copyStream(sink, *source, bufferSize);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CopyStreamResult copyFile(IStreamSink& sink, const IFilesystem& filesystem, const AbsPath& filePath, const ProcessDataCallback& dataCallback, size_t bufferSize)
|
||||
{
|
||||
OUTCOME_TRY(const auto source, filesystem.openStreamSource(filePath, IFilesystem::SourceFlags(IFilesystem::SourceFlag::SequentialHint, IFilesystem::SourceFlag::Unbuffered)));
|
||||
return copyStream(sink, *source, dataCallback, bufferSize);
|
||||
}
|
||||
|
||||
CopyStreamResult copyFile(IFilesystem& dstFilesystem, const AbsPath& dstFilePath, const IFilesystem& srcFilesystem, const AbsPath& srcFilePath, size_t bufferSize)
|
||||
{
|
||||
OUTCOME_TRY(const auto sink, dstFilesystem.openStreamSink(dstFilePath, fs::Mode::CreateOrOpenAndClear));
|
||||
OUTCOME_TRY(const auto source, srcFilesystem.openStreamSource(srcFilePath, IFilesystem::SourceFlags(IFilesystem::SourceFlag::SequentialHint, IFilesystem::SourceFlag::Unbuffered)));
|
||||
return copyStream(*sink, *source, nullptr, bufferSize);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
Reference in New Issue
Block a user