mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-15 22:09:19 -07:00
335cf4f2db
A deep-copy method CopyReader has been added to BlobReader (virtual) and all of its subclasses (override). This should create a second BlobReader to open the same set of data but with an independent read pointer so that it doesn't interfere with any reads done on the original Reader. As part of this, IOFile has added code to create a deep copy IOFile pointer onto the same file, with code based on the platform in question to find the file ID from the file pointer and open a new one. There has also been a small piece added to FileInfo to enable a deep copy, but its only subclass at this time already had a copy constructor so this was relatively minor.
182 lines
3.2 KiB
C++
182 lines
3.2 KiB
C++
// Copyright 2008 Dolphin Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include "Common/IOFile.h"
|
|
|
|
#include <cstddef>
|
|
#include <cstdio>
|
|
#include <string>
|
|
|
|
#ifdef _WIN32
|
|
#include <io.h>
|
|
|
|
#include "Common/CommonFuncs.h"
|
|
#include "Common/StringUtil.h"
|
|
#else
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#ifdef ANDROID
|
|
#include <algorithm>
|
|
|
|
#include "jni/AndroidCommon/AndroidCommon.h"
|
|
#endif
|
|
|
|
#include "Common/CommonTypes.h"
|
|
#include "Common/FileUtil.h"
|
|
|
|
namespace File
|
|
{
|
|
IOFile::IOFile() : m_file(nullptr), m_good(true)
|
|
{
|
|
}
|
|
|
|
IOFile::IOFile(std::FILE* file) : m_file(file), m_good(true)
|
|
{
|
|
}
|
|
|
|
IOFile::IOFile(const std::string& filename, const char openmode[], SharedAccess sh)
|
|
: m_file(nullptr), m_good(true)
|
|
{
|
|
Open(filename, openmode, sh);
|
|
}
|
|
|
|
IOFile::~IOFile()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
IOFile::IOFile(IOFile&& other) noexcept : m_file(nullptr), m_good(true)
|
|
{
|
|
Swap(other);
|
|
}
|
|
|
|
IOFile& IOFile::operator=(IOFile&& other) noexcept
|
|
{
|
|
Swap(other);
|
|
return *this;
|
|
}
|
|
|
|
void IOFile::Swap(IOFile& other) noexcept
|
|
{
|
|
std::swap(m_file, other.m_file);
|
|
std::swap(m_good, other.m_good);
|
|
}
|
|
|
|
bool IOFile::Open(const std::string& filename, const char openmode[],
|
|
[[maybe_unused]] SharedAccess sh)
|
|
{
|
|
Close();
|
|
|
|
#ifdef _WIN32
|
|
if (sh == SharedAccess::Default)
|
|
{
|
|
m_good = _tfopen_s(&m_file, UTF8ToTStr(filename).c_str(), UTF8ToTStr(openmode).c_str()) == 0;
|
|
}
|
|
else if (sh == SharedAccess::Read)
|
|
{
|
|
m_file = _tfsopen(UTF8ToTStr(filename).c_str(), UTF8ToTStr(openmode).c_str(), SH_DENYWR);
|
|
m_good = m_file != nullptr;
|
|
}
|
|
#else
|
|
#ifdef ANDROID
|
|
if (IsPathAndroidContent(filename))
|
|
m_file = fdopen(OpenAndroidContent(filename, OpenModeToAndroid(openmode)), openmode);
|
|
else
|
|
#endif
|
|
m_file = std::fopen(filename.c_str(), openmode);
|
|
|
|
m_good = m_file != nullptr;
|
|
#endif
|
|
|
|
return m_good;
|
|
}
|
|
|
|
bool IOFile::Close()
|
|
{
|
|
if (!IsOpen() || 0 != std::fclose(m_file))
|
|
m_good = false;
|
|
|
|
m_file = nullptr;
|
|
return m_good;
|
|
}
|
|
|
|
IOFile IOFile::Duplicate(const char openmode[]) const
|
|
{
|
|
#ifdef _WIN32
|
|
return IOFile(_fdopen(_dup(_fileno(m_file)), openmode));
|
|
#else // _WIN32
|
|
return IOFile(fdopen(dup(fileno(m_file)), openmode));
|
|
#endif // _WIN32
|
|
}
|
|
|
|
void IOFile::SetHandle(std::FILE* file)
|
|
{
|
|
Close();
|
|
ClearError();
|
|
m_file = file;
|
|
}
|
|
|
|
u64 IOFile::GetSize() const
|
|
{
|
|
if (IsOpen())
|
|
return File::GetSize(m_file);
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
bool IOFile::Seek(s64 offset, SeekOrigin origin)
|
|
{
|
|
int fseek_origin;
|
|
switch (origin)
|
|
{
|
|
case SeekOrigin::Begin:
|
|
fseek_origin = SEEK_SET;
|
|
break;
|
|
case SeekOrigin::Current:
|
|
fseek_origin = SEEK_CUR;
|
|
break;
|
|
case SeekOrigin::End:
|
|
fseek_origin = SEEK_END;
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
if (!IsOpen() || 0 != fseeko(m_file, offset, fseek_origin))
|
|
m_good = false;
|
|
|
|
return m_good;
|
|
}
|
|
|
|
u64 IOFile::Tell() const
|
|
{
|
|
if (IsOpen())
|
|
return ftello(m_file);
|
|
else
|
|
return UINT64_MAX;
|
|
}
|
|
|
|
bool IOFile::Flush()
|
|
{
|
|
if (!IsOpen() || 0 != std::fflush(m_file))
|
|
m_good = false;
|
|
|
|
return m_good;
|
|
}
|
|
|
|
bool IOFile::Resize(u64 size)
|
|
{
|
|
#ifdef _WIN32
|
|
if (!IsOpen() || 0 != _chsize_s(_fileno(m_file), size))
|
|
#else
|
|
// TODO: handle 64bit and growing
|
|
if (!IsOpen() || 0 != ftruncate(fileno(m_file), size))
|
|
#endif
|
|
m_good = false;
|
|
|
|
return m_good;
|
|
}
|
|
|
|
} // namespace File
|