From 3a1c0a3452837b4953f7f330ff8abf102f4a6a36 Mon Sep 17 00:00:00 2001 From: disarray2077 <86157825+disarray2077@users.noreply.github.com> Date: Sun, 1 Aug 2021 17:29:01 -0300 Subject: [PATCH 1/6] Change some file writes to UnbufferedFileStream --- BeefLibs/corlib/src/IO/File.bf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/BeefLibs/corlib/src/IO/File.bf b/BeefLibs/corlib/src/IO/File.bf index 06d6abd7..87315500 100644 --- a/BeefLibs/corlib/src/IO/File.bf +++ b/BeefLibs/corlib/src/IO/File.bf @@ -49,7 +49,7 @@ namespace System.IO public static Result WriteAll(StringView path, Span data, bool doAppend = false) { - FileStream fs = scope FileStream(); + UnbufferedFileStream fs = scope UnbufferedFileStream(); var result = fs.Open(path, doAppend ? .Append : .Create, .Write); if (result case .Err) return .Err; @@ -76,7 +76,7 @@ namespace System.IO public static Result WriteAllText(StringView path, StringView text, bool doAppend = false) { - FileStream fs = scope FileStream(); + UnbufferedFileStream fs = scope UnbufferedFileStream(); var result = fs.Open(path, doAppend ? .Append : .Create, .Write); if (result case .Err) return .Err; @@ -87,7 +87,7 @@ namespace System.IO public static Result WriteAllText(StringView path, StringView text, Encoding encoding) { - FileStream fs = scope FileStream(); + UnbufferedFileStream fs = scope UnbufferedFileStream(); int len = encoding.GetEncodedSize(text); uint8* data = new uint8[len]*; From a71962a5a80918b070f5c43d932e907f17fa1482 Mon Sep 17 00:00:00 2001 From: disarray2077 <86157825+disarray2077@users.noreply.github.com> Date: Sun, 1 Aug 2021 17:30:40 -0300 Subject: [PATCH 2/6] Fix File OpenOrCreate --- BeefLibs/corlib/src/IO/FileStream.bf | 4 ++-- BeefLibs/corlib/src/Platform.bf | 1 + BeefySysLib/platform/PlatformInterface.h | 1 + BeefySysLib/platform/posix/PosixCommon.cpp | 4 ++++ BeefySysLib/platform/win/Platform.cpp | 6 +++++- IDE/mintest/minlib/src/System/Platform.bf | 1 + 6 files changed, 14 insertions(+), 3 deletions(-) diff --git a/BeefLibs/corlib/src/IO/FileStream.bf b/BeefLibs/corlib/src/IO/FileStream.bf index 36b5daa0..3359f561 100644 --- a/BeefLibs/corlib/src/IO/FileStream.bf +++ b/BeefLibs/corlib/src/IO/FileStream.bf @@ -178,7 +178,7 @@ namespace System.IO case .Open: createKind = .OpenExisting; case .OpenOrCreate: - createKind = .CreateAlways; + createKind = .OpenAlways; case .Truncate: createKind = .CreateAlways; createFlags |= .Truncate; @@ -337,7 +337,7 @@ namespace System.IO case .Open: createKind = .OpenExisting; case .OpenOrCreate: - createKind = .CreateAlways; + createKind = .OpenAlways; case .Truncate: createKind = .CreateAlways; createFlags |= .Truncate; diff --git a/BeefLibs/corlib/src/Platform.bf b/BeefLibs/corlib/src/Platform.bf index 8e518186..068c0dc0 100644 --- a/BeefLibs/corlib/src/Platform.bf +++ b/BeefLibs/corlib/src/Platform.bf @@ -271,6 +271,7 @@ namespace System CreateAlways, CreateIfNotExists, OpenExisting, + OpenAlways, }; public enum BfpFileCreateFlags : int32 diff --git a/BeefySysLib/platform/PlatformInterface.h b/BeefySysLib/platform/PlatformInterface.h index aa6fc380..c8434563 100644 --- a/BeefySysLib/platform/PlatformInterface.h +++ b/BeefySysLib/platform/PlatformInterface.h @@ -344,6 +344,7 @@ enum BfpFileCreateKind BfpFileCreateKind_CreateAlways, BfpFileCreateKind_CreateIfNotExists, BfpFileCreateKind_OpenExisting, + BfpFileCreateKind_OpenAlways }; enum BfpFileCreateFlags diff --git a/BeefySysLib/platform/posix/PosixCommon.cpp b/BeefySysLib/platform/posix/PosixCommon.cpp index 4fa4c52b..910703e4 100644 --- a/BeefySysLib/platform/posix/PosixCommon.cpp +++ b/BeefySysLib/platform/posix/PosixCommon.cpp @@ -1858,6 +1858,10 @@ BFP_EXPORT BfpFile* BFP_CALLTYPE BfpFile_Create(const char* inName, BfpFileCreat } return result; }; + + // POSIX doesn't need the OpenAlways kind. + if (createKind == BfpFileCreateKind_OpenAlways) + createKind = BfpFileCreateKind_CreateAlways; BfpFile* bfpFile = NULL; diff --git a/BeefySysLib/platform/win/Platform.cpp b/BeefySysLib/platform/win/Platform.cpp index 81aebe2c..de943727 100644 --- a/BeefySysLib/platform/win/Platform.cpp +++ b/BeefySysLib/platform/win/Platform.cpp @@ -2741,9 +2741,13 @@ BFP_EXPORT BfpFile* BFP_CALLTYPE BfpFile_Create(const char* path, BfpFileCreateK creationDisposition = CREATE_ALWAYS; } else if (createKind == BfpFileCreateKind_CreateIfNotExists) - { + { creationDisposition = CREATE_NEW; } + else if (createKind == BfpFileCreateKind_OpenAlways) + { + creationDisposition = OPEN_ALWAYS; + } else { creationDisposition = OPEN_EXISTING; diff --git a/IDE/mintest/minlib/src/System/Platform.bf b/IDE/mintest/minlib/src/System/Platform.bf index c4259103..217ff2a7 100644 --- a/IDE/mintest/minlib/src/System/Platform.bf +++ b/IDE/mintest/minlib/src/System/Platform.bf @@ -234,6 +234,7 @@ namespace System CreateAlways, CreateIfNotExists, OpenExisting, + OpenAlways, }; public enum BfpFileCreateFlags : int32 From 4bd3cc641d1fb636ca8ccd95cf2f078a4194a33b Mon Sep 17 00:00:00 2001 From: disarray2077 <86157825+disarray2077@users.noreply.github.com> Date: Sun, 1 Aug 2021 17:37:37 -0300 Subject: [PATCH 3/6] Add SeekUnderlying to FileStream --- BeefLibs/corlib/src/IO/FileStream.bf | 64 +++++++++++++--------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/BeefLibs/corlib/src/IO/FileStream.bf b/BeefLibs/corlib/src/IO/FileStream.bf index 3359f561..287de4fa 100644 --- a/BeefLibs/corlib/src/IO/FileStream.bf +++ b/BeefLibs/corlib/src/IO/FileStream.bf @@ -253,6 +253,22 @@ namespace System.IO } } + public override bool CanRead + { + get + { + return mFileAccess.HasFlag(FileAccess.Read); + } + } + + public override bool CanWrite + { + get + { + return mFileAccess.HasFlag(FileAccess.Write); + } + } + public this() { @@ -274,22 +290,6 @@ namespace System.IO mFileAccess = access; } - public override bool CanRead - { - get - { - return mFileAccess.HasFlag(FileAccess.Read); - } - } - - public override bool CanWrite - { - get - { - return mFileAccess.HasFlag(FileAccess.Write); - } - } - public Result Create(StringView path, FileAccess access = .ReadWrite, FileShare share = .None, int bufferSize = 4096, FileOptions options = .None, SecurityAttributes* secAttrs = null) { return Open(path, FileMode.Create, access, share, bufferSize, options, secAttrs); @@ -406,15 +406,20 @@ namespace System.IO mUnderlyingLength = Platform.BfpFile_GetFileSize(mBfpFile); } + protected Result SeekUnderlying(int64 offset, Platform.BfpFileSeekKind seekKind = .Absolute) + { + int64 newPos = Platform.BfpFile_Seek(mBfpFile, offset, seekKind); + Result result = ((seekKind == .Absolute) && (newPos != offset)) ? .Err : .Ok; + if (result case .Ok) + mBfpFilePos = newPos; + return result; + } + protected override Result TryReadUnderlying(int64 pos, Span data) { if (mBfpFilePos != pos) - { - int64 newPos = Platform.BfpFile_Seek(mBfpFile, pos, .Absolute); - if (newPos != pos) - return .Err; - mBfpFilePos = pos; - } + Try!(SeekUnderlying(pos)); + Platform.BfpFileResult result = .Ok; int numBytesRead = Platform.BfpFile_Read(mBfpFile, data.Ptr, data.Length, -1, &result); if ((result != .Ok) && (result != .PartialData)) @@ -426,12 +431,8 @@ namespace System.IO protected override Result TryWriteUnderlying(int64 pos, Span data) { if (mBfpFilePos != pos) - { - int64 newPos = Platform.BfpFile_Seek(mBfpFile, pos, .Absolute); - if (newPos != pos) - return .Err; - mBfpFilePos = pos; - } + Try!(SeekUnderlying(pos)); + Platform.BfpFileResult result = .Ok; int numBytesRead = Platform.BfpFile_Write(mBfpFile, data.Ptr, data.Length, -1, &result); if ((result != .Ok) && (result != .PartialData)) @@ -443,12 +444,7 @@ namespace System.IO public Result TryRead(Span data, int timeoutMS) { if (mBfpFilePos != mPos) - { - int64 newPos = Platform.BfpFile_Seek(mBfpFile, mPos, .Absolute); - if (newPos != mPos) - return .Err; - mBfpFilePos = mPos; - } + Try!(SeekUnderlying(mPos)); Platform.BfpFileResult result = .Ok; int numBytesRead = Platform.BfpFile_Read(mBfpFile, data.Ptr, data.Length, timeoutMS, &result); From 06fe5a98c6d41f4bfca6bab2b63a5d5de7b5652b Mon Sep 17 00:00:00 2001 From: disarray2077 <86157825+disarray2077@users.noreply.github.com> Date: Sun, 1 Aug 2021 17:38:30 -0300 Subject: [PATCH 4/6] Implement FileStream SetLength --- BeefLibs/corlib/src/IO/FileStream.bf | 60 ++++++++++++++++++++++ BeefLibs/corlib/src/IO/Stream.bf | 5 ++ BeefLibs/corlib/src/Platform.bf | 2 +- BeefySysLib/FileStream.cpp | 3 +- BeefySysLib/platform/PlatformInterface.h | 2 +- BeefySysLib/platform/posix/PosixCommon.cpp | 10 ++-- BeefySysLib/platform/win/Platform.cpp | 9 +++- IDE/mintest/minlib/src/System/Platform.bf | 2 +- 8 files changed, 83 insertions(+), 10 deletions(-) diff --git a/BeefLibs/corlib/src/IO/FileStream.bf b/BeefLibs/corlib/src/IO/FileStream.bf index 287de4fa..9df7f8a3 100644 --- a/BeefLibs/corlib/src/IO/FileStream.bf +++ b/BeefLibs/corlib/src/IO/FileStream.bf @@ -235,6 +235,32 @@ namespace System.IO return .Err; return .Ok; } + + public override Result SetLength(int64 length) + { + int64 pos = Position; + + if (pos != length) + Seek(length); + + Platform.BfpFileResult result = .Ok; + Platform.BfpFile_Truncate(mBfpFile, &result); + if (result != .Ok) + { + Seek(pos); + return .Err; + } + + if (pos != length) + { + if (pos < length) + Seek(pos); + else + Seek(0, .FromEnd); + } + + return .Ok; + } } class BufferedFileStream : BufferedStream @@ -452,6 +478,40 @@ namespace System.IO return .Err; return numBytesRead; } + + public override Result SetLength(int64 length) + { + Try!(Flush()); + + int64 pos = Position; + + if (pos != length || pos != mBfpFilePos) + { + Try!(SeekUnderlying(length)); + mPos = length; + } + + Platform.BfpFileResult result = .Ok; + Platform.BfpFile_Truncate(mBfpFile, &result); + if (result != .Ok) + { + Try!(SeekUnderlying(pos)); + return .Err; + } + + mUnderlyingLength = length; + mPos = Math.Min(pos, Length); + + if (pos != length) + { + if (pos < length) + Try!(SeekUnderlying(pos)); + else + Try!(SeekUnderlying(0, .FromEnd)); + } + + return .Ok; + } } class FileStream : BufferedFileStream diff --git a/BeefLibs/corlib/src/IO/Stream.bf b/BeefLibs/corlib/src/IO/Stream.bf index 00e8bab5..404a5d8b 100644 --- a/BeefLibs/corlib/src/IO/Stream.bf +++ b/BeefLibs/corlib/src/IO/Stream.bf @@ -203,6 +203,11 @@ namespace System.IO return .Ok; } + public virtual Result SetLength(int64 length) + { + return .Err; + } + public void Align(int alignSize) { int64 pos = Length; diff --git a/BeefLibs/corlib/src/Platform.bf b/BeefLibs/corlib/src/Platform.bf index 068c0dc0..f110c709 100644 --- a/BeefLibs/corlib/src/Platform.bf +++ b/BeefLibs/corlib/src/Platform.bf @@ -352,7 +352,7 @@ namespace System [CallingConvention(.Stdcall), CLink] public static extern int64 BfpFile_Seek(BfpFile* file, int64 offset, BfpFileSeekKind seekKind); [CallingConvention(.Stdcall), CLink] - public static extern void BfpFile_Truncate(BfpFile* file); + public static extern void BfpFile_Truncate(BfpFile* file, BfpFileResult* outResult); [CallingConvention(.Stdcall), CLink] public static extern BfpTimeStamp BfpFile_GetTime_LastWrite(char8* path); [CallingConvention(.Stdcall), CLink] diff --git a/BeefySysLib/FileStream.cpp b/BeefySysLib/FileStream.cpp index 1e850d76..08ee6f3d 100644 --- a/BeefySysLib/FileStream.cpp +++ b/BeefySysLib/FileStream.cpp @@ -219,7 +219,8 @@ void SysFileStream::SetSizeFast(int size) int curPos = GetPos(); SetPos(size); - BfpFile_Truncate(mFile); + BfpFileResult result = BfpFileResult_Ok; + BfpFile_Truncate(mFile, &result); SetPos(curPos); return; } diff --git a/BeefySysLib/platform/PlatformInterface.h b/BeefySysLib/platform/PlatformInterface.h index c8434563..79b08843 100644 --- a/BeefySysLib/platform/PlatformInterface.h +++ b/BeefySysLib/platform/PlatformInterface.h @@ -422,7 +422,7 @@ BFP_EXPORT intptr BFP_CALLTYPE BfpFile_Read(BfpFile* file, void* buffer, intptr BFP_EXPORT void BFP_CALLTYPE BfpFile_Flush(BfpFile* file); BFP_EXPORT int64 BFP_CALLTYPE BfpFile_GetFileSize(BfpFile* file); BFP_EXPORT int64 BFP_CALLTYPE BfpFile_Seek(BfpFile* file, int64 offset, BfpFileSeekKind seekKind); -BFP_EXPORT void BFP_CALLTYPE BfpFile_Truncate(BfpFile* file); +BFP_EXPORT void BFP_CALLTYPE BfpFile_Truncate(BfpFile* file, BfpFileResult* outResult); BFP_EXPORT BfpTimeStamp BFP_CALLTYPE BfpFile_GetTime_LastWrite(const char* path); BFP_EXPORT BfpFileAttributes BFP_CALLTYPE BfpFile_GetAttributes(const char* path, BfpFileResult* outResult); BFP_EXPORT void BFP_CALLTYPE BfpFile_SetAttributes(const char* path, BfpFileAttributes attribs, BfpFileResult* outResult); diff --git a/BeefySysLib/platform/posix/PosixCommon.cpp b/BeefySysLib/platform/posix/PosixCommon.cpp index 910703e4..9e55deda 100644 --- a/BeefySysLib/platform/posix/PosixCommon.cpp +++ b/BeefySysLib/platform/posix/PosixCommon.cpp @@ -2083,13 +2083,15 @@ BFP_EXPORT int64 BFP_CALLTYPE BfpFile_Seek(BfpFile* file, int64 offset, BfpFileS return lseek64(file->mHandle, offset, whence); } -BFP_EXPORT void BFP_CALLTYPE BfpFile_Truncate(BfpFile* file) +BFP_EXPORT void BFP_CALLTYPE BfpFile_Truncate(BfpFile* file, BfpFileResult* outResult) { int64 curPos = (int64)lseek64(file->mHandle, 0, SEEK_CUR); if (ftruncate64(file->mHandle, curPos) != 0) - { - //TODO: Report error? - } + { + OUTRESULT(BfpFileResult_UnknownError); + return; + } + OUTRESULT(BfpFileResult_Ok); } BFP_EXPORT BfpTimeStamp BFP_CALLTYPE BfpFile_GetTime_LastWrite(const char* path) diff --git a/BeefySysLib/platform/win/Platform.cpp b/BeefySysLib/platform/win/Platform.cpp index de943727..e8a91d1e 100644 --- a/BeefySysLib/platform/win/Platform.cpp +++ b/BeefySysLib/platform/win/Platform.cpp @@ -3023,9 +3023,14 @@ BFP_EXPORT int64 BFP_CALLTYPE BfpFile_Seek(BfpFile* file, int64 offset, BfpFileS return newPos.QuadPart; } -BFP_EXPORT void BFP_CALLTYPE BfpFile_Truncate(BfpFile* file) +BFP_EXPORT void BFP_CALLTYPE BfpFile_Truncate(BfpFile* file, BfpFileResult* outResult) { - SetEndOfFile(file->mHandle); + if (!SetEndOfFile(file->mHandle)) + { + OUTRESULT(BfpFileResult_UnknownError); + return; + } + OUTRESULT(BfpFileResult_Ok); } BFP_EXPORT BfpTimeStamp BFP_CALLTYPE BfpFile_GetTime_LastWrite(const char* path) diff --git a/IDE/mintest/minlib/src/System/Platform.bf b/IDE/mintest/minlib/src/System/Platform.bf index 217ff2a7..35a72d33 100644 --- a/IDE/mintest/minlib/src/System/Platform.bf +++ b/IDE/mintest/minlib/src/System/Platform.bf @@ -304,7 +304,7 @@ namespace System [CallingConvention(.Stdcall), CLink] public static extern int64 BfpFile_Seek(BfpFile* file, int64 offset, BfpFileSeekKind seekKind); [CallingConvention(.Stdcall), CLink] - public static extern void BfpFile_Truncate(BfpFile* file); + public static extern void BfpFile_Truncate(BfpFile* file, BfpFileResult* outResult); [CallingConvention(.Stdcall), CLink] public static extern BfpTimeStamp BfpFile_GetTime_LastWrite(char8* path); [CallingConvention(.Stdcall), CLink] From 8a210699c7fd9566d789a3c8ba663509cd2b3314 Mon Sep 17 00:00:00 2001 From: disarray2077 <86157825+disarray2077@users.noreply.github.com> Date: Sun, 1 Aug 2021 17:40:29 -0300 Subject: [PATCH 5/6] Improve WriteTextFile safety --- BeefLibs/Beefy2D/src/Utils.bf | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/BeefLibs/Beefy2D/src/Utils.bf b/BeefLibs/Beefy2D/src/Utils.bf index 06fd2d66..299a1ac0 100644 --- a/BeefLibs/Beefy2D/src/Utils.bf +++ b/BeefLibs/Beefy2D/src/Utils.bf @@ -295,11 +295,13 @@ namespace Beefy public static Result WriteTextFile(StringView path, StringView text) { - var stream = scope FileStream(); - if (stream.Create(path) case .Err) - { + var stream = scope UnbufferedFileStream(); + if (stream.Open(path, .OpenOrCreate, .Write) case .Err) return .Err; - } + + if (stream.SetLength(text.Length) case .Err) + return .Err; + if (stream.WriteStrUnsized(text) case .Err) return .Err; From ba8e816e14c9d154279b16b28e33ecf96f0094bf Mon Sep 17 00:00:00 2001 From: disarray2077 <86157825+disarray2077@users.noreply.github.com> Date: Sun, 1 Aug 2021 17:44:23 -0300 Subject: [PATCH 6/6] Fix a error propagation issue in BufferedStream --- BeefLibs/corlib/src/IO/BufferedStream.bf | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/BeefLibs/corlib/src/IO/BufferedStream.bf b/BeefLibs/corlib/src/IO/BufferedStream.bf index a3d6048c..08bde0ac 100644 --- a/BeefLibs/corlib/src/IO/BufferedStream.bf +++ b/BeefLibs/corlib/src/IO/BufferedStream.bf @@ -88,14 +88,12 @@ namespace System.IO data.RemoveFromStart((.)spaceLeft); } - if (mWriteDirtyPos >= 0) - Try!(Flush()); + Try!(Flush()); if ((mBuffer == null) || (data.Length > mBuffer.Count)) { - var result = TryReadUnderlying(mPos, data); - if (result case .Ok(let len)) - mPos += len; + let len = Try!(TryReadUnderlying(mPos, data)); + mPos += len; return (.)(mPos - readStart); } @@ -148,10 +146,9 @@ namespace System.IO if ((mBuffer == null) || (data.Length > mBuffer.Count)) { - var result = TryWriteUnderlying(mPos, data); - if (result case .Ok(let len)) - mPos += len; - writeCount += result; + let len = Try!(TryWriteUnderlying(mPos, data)); + mPos += len; + writeCount += len; return writeCount; }