ByteStream: Add error feedback
This commit is contained in:
parent
f4584f48f9
commit
9dd686a994
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "byte_stream.h"
|
#include "byte_stream.h"
|
||||||
#include "assert.h"
|
#include "assert.h"
|
||||||
|
#include "error.h"
|
||||||
#include "file_system.h"
|
#include "file_system.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "string_util.h"
|
#include "string_util.h"
|
||||||
|
@ -981,13 +982,16 @@ bool ByteStream::WriteSizePrefixedString(const std::string_view& str)
|
||||||
return (Write2(&size, sizeof(size)) && (size == 0 || Write2(str.data(), size)));
|
return (Write2(&size, sizeof(size)) && (size == 0 || Write2(str.data(), size)));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<ByteStream> ByteStream::OpenFile(const char* fileName, u32 openMode)
|
std::unique_ptr<ByteStream> ByteStream::OpenFile(const char* fileName, u32 openMode, Error* error)
|
||||||
{
|
{
|
||||||
if ((openMode & (BYTESTREAM_OPEN_CREATE | BYTESTREAM_OPEN_WRITE)) == BYTESTREAM_OPEN_WRITE)
|
if ((openMode & (BYTESTREAM_OPEN_CREATE | BYTESTREAM_OPEN_WRITE)) == BYTESTREAM_OPEN_WRITE)
|
||||||
{
|
{
|
||||||
// if opening with write but not create, the path must exist.
|
// if opening with write but not create, the path must exist.
|
||||||
if (!FileSystem::FileExists(fileName))
|
if (!FileSystem::FileExists(fileName))
|
||||||
|
{
|
||||||
|
Error::SetStringView(error, "File does not exist.");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char modeString[16];
|
char modeString[16];
|
||||||
|
@ -1050,12 +1054,16 @@ std::unique_ptr<ByteStream> ByteStream::OpenFile(const char* fileName, u32 openM
|
||||||
CreateFileW(wideTemporaryFileName.c_str(), desiredAccess, FILE_SHARE_DELETE, NULL, CREATE_NEW, 0, NULL);
|
CreateFileW(wideTemporaryFileName.c_str(), desiredAccess, FILE_SHARE_DELETE, NULL, CREATE_NEW, 0, NULL);
|
||||||
|
|
||||||
if (hFile == INVALID_HANDLE_VALUE)
|
if (hFile == INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
Error::SetWin32(error, "CreateFileW() failed: ", GetLastError());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// get fd from this
|
// get fd from this
|
||||||
int fd = _open_osfhandle(reinterpret_cast<intptr_t>(hFile), 0);
|
int fd = _open_osfhandle(reinterpret_cast<intptr_t>(hFile), 0);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
|
Error::SetErrno(error, "_open_osfhandle() failed: ", errno);
|
||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
DeleteFileW(wideTemporaryFileName.c_str());
|
DeleteFileW(wideTemporaryFileName.c_str());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1065,6 +1073,7 @@ std::unique_ptr<ByteStream> ByteStream::OpenFile(const char* fileName, u32 openM
|
||||||
FILE* pTemporaryFile = _fdopen(fd, modeString);
|
FILE* pTemporaryFile = _fdopen(fd, modeString);
|
||||||
if (!pTemporaryFile)
|
if (!pTemporaryFile)
|
||||||
{
|
{
|
||||||
|
Error::SetErrno(error, "_fdopen() failed: ", errno);
|
||||||
_close(fd);
|
_close(fd);
|
||||||
DeleteFileW(wideTemporaryFileName.c_str());
|
DeleteFileW(wideTemporaryFileName.c_str());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1077,7 +1086,7 @@ std::unique_ptr<ByteStream> ByteStream::OpenFile(const char* fileName, u32 openM
|
||||||
// do we need to copy the existing file into this one?
|
// do we need to copy the existing file into this one?
|
||||||
if (!(openMode & BYTESTREAM_OPEN_TRUNCATE))
|
if (!(openMode & BYTESTREAM_OPEN_TRUNCATE))
|
||||||
{
|
{
|
||||||
FILE* pOriginalFile = FileSystem::OpenCFile(fileName, "rb");
|
std::FILE* pOriginalFile = FileSystem::OpenCFile(fileName, "rb", error);
|
||||||
if (!pOriginalFile)
|
if (!pOriginalFile)
|
||||||
{
|
{
|
||||||
// this will delete the temporary file
|
// this will delete the temporary file
|
||||||
|
@ -1087,14 +1096,15 @@ std::unique_ptr<ByteStream> ByteStream::OpenFile(const char* fileName, u32 openM
|
||||||
|
|
||||||
static const size_t BUFFERSIZE = 4096;
|
static const size_t BUFFERSIZE = 4096;
|
||||||
u8 buffer[BUFFERSIZE];
|
u8 buffer[BUFFERSIZE];
|
||||||
while (!feof(pOriginalFile))
|
while (!std::feof(pOriginalFile))
|
||||||
{
|
{
|
||||||
size_t nBytes = fread(buffer, BUFFERSIZE, sizeof(u8), pOriginalFile);
|
size_t nBytes = std::fread(buffer, BUFFERSIZE, sizeof(u8), pOriginalFile);
|
||||||
if (nBytes == 0)
|
if (nBytes == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (pStream->Write(buffer, (u32)nBytes) != (u32)nBytes)
|
if (pStream->Write(buffer, (u32)nBytes) != (u32)nBytes)
|
||||||
{
|
{
|
||||||
|
Error::SetStringView(error, "Failed to copy file contents.");
|
||||||
pStream->Discard();
|
pStream->Discard();
|
||||||
fclose(pOriginalFile);
|
fclose(pOriginalFile);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1123,7 +1133,7 @@ std::unique_ptr<ByteStream> ByteStream::OpenFile(const char* fileName, u32 openM
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// open the file
|
// open the file
|
||||||
std::FILE* pTemporaryFile = FileSystem::OpenCFile(temporaryFileName, modeString);
|
std::FILE* pTemporaryFile = FileSystem::OpenCFile(temporaryFileName, modeString, error);
|
||||||
if (pTemporaryFile == nullptr)
|
if (pTemporaryFile == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
@ -1134,7 +1144,7 @@ std::unique_ptr<ByteStream> ByteStream::OpenFile(const char* fileName, u32 openM
|
||||||
// do we need to copy the existing file into this one?
|
// do we need to copy the existing file into this one?
|
||||||
if (!(openMode & BYTESTREAM_OPEN_TRUNCATE))
|
if (!(openMode & BYTESTREAM_OPEN_TRUNCATE))
|
||||||
{
|
{
|
||||||
std::FILE* pOriginalFile = FileSystem::OpenCFile(fileName, "rb");
|
std::FILE* pOriginalFile = FileSystem::OpenCFile(fileName, "rb", error);
|
||||||
if (!pOriginalFile)
|
if (!pOriginalFile)
|
||||||
{
|
{
|
||||||
// this will delete the temporary file
|
// this will delete the temporary file
|
||||||
|
@ -1152,6 +1162,7 @@ std::unique_ptr<ByteStream> ByteStream::OpenFile(const char* fileName, u32 openM
|
||||||
|
|
||||||
if (pStream->Write(buffer, (u32)nBytes) != (u32)nBytes)
|
if (pStream->Write(buffer, (u32)nBytes) != (u32)nBytes)
|
||||||
{
|
{
|
||||||
|
Error::SetStringView(error, "Failed to copy file contents.");
|
||||||
pStream->SetErrorState();
|
pStream->SetErrorState();
|
||||||
std::fclose(pOriginalFile);
|
std::fclose(pOriginalFile);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1169,7 +1180,7 @@ std::unique_ptr<ByteStream> ByteStream::OpenFile(const char* fileName, u32 openM
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// forward through
|
// forward through
|
||||||
std::FILE* pFile = FileSystem::OpenCFile(fileName, modeString);
|
std::FILE* pFile = FileSystem::OpenCFile(fileName, modeString, error);
|
||||||
if (!pFile)
|
if (!pFile)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
class Error;
|
||||||
|
|
||||||
// base byte stream creation functions
|
// base byte stream creation functions
|
||||||
enum BYTESTREAM_OPEN_MODE
|
enum BYTESTREAM_OPEN_MODE
|
||||||
{
|
{
|
||||||
|
@ -104,7 +106,7 @@ public:
|
||||||
|
|
||||||
// base byte stream creation functions
|
// base byte stream creation functions
|
||||||
// opens a local file-based stream. fills in error if passed, and returns false if the file cannot be opened.
|
// opens a local file-based stream. fills in error if passed, and returns false if the file cannot be opened.
|
||||||
static std::unique_ptr<ByteStream> OpenFile(const char* FileName, u32 OpenMode);
|
static std::unique_ptr<ByteStream> OpenFile(const char* FileName, u32 OpenMode, Error* error = nullptr);
|
||||||
|
|
||||||
// memory byte stream, caller is responsible for management, therefore it can be located on either the stack or on the
|
// memory byte stream, caller is responsible for management, therefore it can be located on either the stack or on the
|
||||||
// heap.
|
// heap.
|
||||||
|
|
Loading…
Reference in New Issue