dolphin/Source/Core/DiscIO/FileBlob.cpp
JosJuice 9a01c3fb9f Use positional arguments in all translatable fmt strings
We want to use positional arguments in translatable strings
that have more than one argument so that translators can change
the order of them, but the question is: Should we also use
positional arguments in translatable strings with only one
argument? I think it makes most sense that way, partially
so that translators don't even have to be aware of the
non-positional syntax and partially because "translatable
strings use positional arguments" is an easier rule for us
to remember than "transitional strings which have more than
one argument use positional arguments". But let me know if
you have a different opinion.
2020-11-16 13:28:11 +01:00

117 lines
2.8 KiB
C++

// Copyright 2008 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <algorithm>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "Common/Assert.h"
#include "Common/FileUtil.h"
#include "Common/MsgHandler.h"
#include "DiscIO/FileBlob.h"
namespace DiscIO
{
PlainFileReader::PlainFileReader(File::IOFile file) : m_file(std::move(file))
{
m_size = m_file.GetSize();
}
std::unique_ptr<PlainFileReader> PlainFileReader::Create(File::IOFile file)
{
if (file)
return std::unique_ptr<PlainFileReader>(new PlainFileReader(std::move(file)));
return nullptr;
}
bool PlainFileReader::Read(u64 offset, u64 nbytes, u8* out_ptr)
{
if (m_file.Seek(offset, SEEK_SET) && m_file.ReadBytes(out_ptr, nbytes))
{
return true;
}
else
{
m_file.Clear();
return false;
}
}
bool ConvertToPlain(BlobReader* infile, const std::string& infile_path,
const std::string& outfile_path, CompressCB callback)
{
ASSERT(infile->IsDataSizeAccurate());
File::IOFile outfile(outfile_path, "wb");
if (!outfile)
{
PanicAlertFmtT(
"Failed to open the output file \"{0}\".\n"
"Check that you have permissions to write the target folder and that the media can "
"be written.",
outfile_path);
return false;
}
constexpr size_t DESIRED_BUFFER_SIZE = 0x80000;
u64 buffer_size = infile->GetBlockSize();
if (buffer_size == 0)
{
buffer_size = DESIRED_BUFFER_SIZE;
}
else
{
while (buffer_size < DESIRED_BUFFER_SIZE)
buffer_size *= 2;
}
std::vector<u8> buffer(buffer_size);
const u64 num_buffers = (infile->GetDataSize() + buffer_size - 1) / buffer_size;
int progress_monitor = std::max<int>(1, num_buffers / 100);
bool success = true;
for (u64 i = 0; i < num_buffers; i++)
{
if (i % progress_monitor == 0)
{
const bool was_cancelled =
!callback(Common::GetStringT("Unpacking"), (float)i / (float)num_buffers);
if (was_cancelled)
{
success = false;
break;
}
}
const u64 inpos = i * buffer_size;
const u64 sz = std::min(buffer_size, infile->GetDataSize() - inpos);
if (!infile->Read(inpos, sz, buffer.data()))
{
PanicAlertFmtT("Failed to read from the input file \"{0}\".", infile_path);
success = false;
break;
}
if (!outfile.WriteBytes(buffer.data(), sz))
{
PanicAlertFmtT("Failed to write the output file \"{0}\".\n"
"Check that you have enough space available on the target drive.",
outfile_path);
success = false;
break;
}
}
if (!success)
{
// Remove the incomplete output file.
outfile.Close();
File::Delete(outfile_path);
}
return success;
}
} // namespace DiscIO