Core/File: Add OpenMode::Defer

This commit is contained in:
SirLynix 2023-03-03 13:14:28 +01:00
parent 36d7e98299
commit 6bf4304817
4 changed files with 45 additions and 3 deletions

View File

@ -97,6 +97,7 @@ namespace Nz
NotOpen, // Use the current mod of opening NotOpen, // Use the current mod of opening
Append, // Disable writing on existing parts and put the cursor at the end Append, // Disable writing on existing parts and put the cursor at the end
Defer, // Defer file opening until a read/write operation is performed on it
Lock, // Disable modifying the file before it is open Lock, // Disable modifying the file before it is open
MustExist, // Fail if the file doesn't exists, even if opened in write mode MustExist, // Fail if the file doesn't exists, even if opened in write mode
ReadOnly, // Open in read only ReadOnly, // Open in read only

View File

@ -60,6 +60,7 @@ namespace Nz
static bool WriteWhole(const std::filesystem::path& path, const void* data, std::size_t size); static bool WriteWhole(const std::filesystem::path& path, const void* data, std::size_t size);
private: private:
inline bool CheckFileOpening();
void FlushStream() override; void FlushStream() override;
std::size_t ReadBlock(void* buffer, std::size_t size) override; std::size_t ReadBlock(void* buffer, std::size_t size) override;
bool SeekStreamCursor(UInt64 offset) override; bool SeekStreamCursor(UInt64 offset) override;

View File

@ -33,6 +33,20 @@ namespace Nz
{ {
return Nz::ComputeHash(hash, File(filePath)); return Nz::ComputeHash(hash, File(filePath));
} }
inline bool File::CheckFileOpening()
{
if (m_openMode.Test(OpenMode::Defer))
{
if (!Open(m_filePath, m_openMode & ~OpenMode::Defer))
{
NazaraError("failed to open file");
return false;
}
}
return true;
}
} }
#include <Nazara/Core/DebugOff.hpp> #include <Nazara/Core/DebugOff.hpp>

View File

@ -181,15 +181,21 @@ namespace Nz
if (openMode == OpenMode::NotOpen) if (openMode == OpenMode::NotOpen)
return false; return false;
m_openMode = openMode;
if (m_openMode.Test(OpenMode::Defer))
{
// defer opening until a read/write operation is performed
return true;
}
std::unique_ptr<FileImpl> impl = std::make_unique<FileImpl>(this); std::unique_ptr<FileImpl> impl = std::make_unique<FileImpl>(this);
if (!impl->Open(m_filePath, openMode)) if (!impl->Open(m_filePath, openMode))
{ {
ErrorFlags flags(ErrorMode::Silent); // Silent by default ErrorFlags flags(ErrorMode::Silent); // Silent by default
NazaraError("Failed to open \"" + m_filePath.generic_u8string() + "\": " + Error::GetLastSystemError()); NazaraError("failed to open \"" + m_filePath.generic_u8string() + "\": " + Error::GetLastSystemError());
return false; return false;
} }
m_openMode = openMode;
m_impl = std::move(impl); m_impl = std::move(impl);
EnableBuffering(!m_openMode.Test(OpenMode::Unbuffered)); EnableBuffering(!m_openMode.Test(OpenMode::Unbuffered));
@ -259,6 +265,9 @@ namespace Nz
*/ */
bool File::SetSize(UInt64 size) bool File::SetSize(UInt64 size)
{ {
if (!CheckFileOpening())
return false;
NazaraAssert(IsOpen(), "File is not open"); NazaraAssert(IsOpen(), "File is not open");
NazaraAssert(IsWritable(), "File is not writable"); NazaraAssert(IsWritable(), "File is not writable");
@ -313,6 +322,9 @@ namespace Nz
void File::FlushStream() void File::FlushStream()
{ {
if (!IsOpen() && m_openMode.Test(OpenMode::Defer))
return;
NazaraAssert(IsOpen(), "File is not open"); NazaraAssert(IsOpen(), "File is not open");
m_impl->Flush(); m_impl->Flush();
@ -330,6 +342,9 @@ namespace Nz
std::size_t File::ReadBlock(void* buffer, std::size_t size) std::size_t File::ReadBlock(void* buffer, std::size_t size)
{ {
if (!CheckFileOpening())
return false;
NazaraAssert(IsOpen(), "File is not open"); NazaraAssert(IsOpen(), "File is not open");
if (size == 0) if (size == 0)
@ -359,6 +374,9 @@ namespace Nz
bool File::SeekStreamCursor(UInt64 offset) bool File::SeekStreamCursor(UInt64 offset)
{ {
if (!CheckFileOpening())
return false;
NazaraAssert(IsOpen(), "File is not open"); NazaraAssert(IsOpen(), "File is not open");
return m_impl->SetCursorPos(CursorPosition::AtBegin, offset); return m_impl->SetCursorPos(CursorPosition::AtBegin, offset);
@ -372,6 +390,9 @@ namespace Nz
*/ */
UInt64 File::TellStreamCursor() const UInt64 File::TellStreamCursor() const
{ {
if (!IsOpen() && m_openMode.Test(OpenMode::Defer))
return 0;
NazaraAssert(IsOpen(), "File is not open"); NazaraAssert(IsOpen(), "File is not open");
return m_impl->GetCursorPos(); return m_impl->GetCursorPos();
@ -385,6 +406,9 @@ namespace Nz
*/ */
bool File::TestStreamEnd() const bool File::TestStreamEnd() const
{ {
if (!IsOpen() && m_openMode.Test(OpenMode::Defer))
return false;
NazaraAssert(IsOpen(), "File is not open"); NazaraAssert(IsOpen(), "File is not open");
return m_impl->EndOfFile(); return m_impl->EndOfFile();
@ -402,6 +426,9 @@ namespace Nz
*/ */
std::size_t File::WriteBlock(const void* buffer, std::size_t size) std::size_t File::WriteBlock(const void* buffer, std::size_t size)
{ {
if (!CheckFileOpening())
return false;
NazaraAssert(IsOpen(), "File is not open"); NazaraAssert(IsOpen(), "File is not open");
if (size == 0) if (size == 0)
@ -423,7 +450,6 @@ namespace Nz
* \remark Produces a NazaraError if file could not be open * \remark Produces a NazaraError if file could not be open
* \remark Produces a NazaraError if file could not be read * \remark Produces a NazaraError if file could not be read
*/ */
NAZARA_CORE_API bool HashAppend(AbstractHash& hash, const File& originalFile) NAZARA_CORE_API bool HashAppend(AbstractHash& hash, const File& originalFile)
{ {
File file(originalFile.GetPath()); File file(originalFile.GetPath());