From 0f944bc0a15f75594c3cec65572356868901394a Mon Sep 17 00:00:00 2001 From: flysand7 Date: Sun, 24 Mar 2024 10:22:57 +1100 Subject: [PATCH 1/3] [core/os2]: Reading from unsized files --- core/os/os2/errors.odin | 16 ++++++++++++ core/os/os2/file_util.odin | 46 ++++++++++++++++++++++++++--------- core/os/os2/file_windows.odin | 4 ++- 3 files changed, 54 insertions(+), 12 deletions(-) diff --git a/core/os/os2/errors.odin b/core/os/os2/errors.odin index 426375a5a..77c5b1199 100644 --- a/core/os/os2/errors.odin +++ b/core/os/os2/errors.odin @@ -13,6 +13,10 @@ General_Error :: enum u32 { Timeout, + // Indicates that an attempt to retrieve a file's size was made, but the + // file doesn't have a size. + No_Size, + Invalid_File, Invalid_Dir, Invalid_Path, @@ -22,9 +26,15 @@ General_Error :: enum u32 { Platform_Error :: enum i32 {None=0} +Read_Error :: enum u32 { + None, + Broken_Pipe, +} + Error :: union #shared_nil { General_Error, io.Error, + Read_Error, runtime.Allocator_Error, Platform_Error, } @@ -51,6 +61,7 @@ error_string :: proc(ferr: Error) -> string { case .Not_Exist: return "file does not exist" case .Closed: return "file already closed" case .Timeout: return "i/o timeout" + case .No_Size: return "file has no definite size" case .Invalid_File: return "invalid file" case .Invalid_Dir: return "invalid directory" case .Invalid_Path: return "invalid path" @@ -82,6 +93,11 @@ error_string :: proc(ferr: Error) -> string { case .Invalid_Argument: return "invalid allocator argument" case .Mode_Not_Implemented: return "allocator mode not implemented" } + case Read_Error: + switch e { + case .None: return "" + case .Broken_Pipe: return "Broken pipe" + } case Platform_Error: return _error_string(i32(e)) } diff --git a/core/os/os2/file_util.odin b/core/os/os2/file_util.odin index 459544fc0..bb3dfd9eb 100644 --- a/core/os/os2/file_util.odin +++ b/core/os/os2/file_util.odin @@ -87,26 +87,50 @@ read_entire_file_from_path :: proc(name: string, allocator: runtime.Allocator) - read_entire_file_from_file :: proc(f: ^File, allocator: runtime.Allocator) -> (data: []byte, err: Error) { size: int + has_size := true if size64, err := file_size(f); err == nil { if i64(int(size64)) != size64 { size = int(size64) } + } else if err == .No_Size { + has_size = false + } else { + return } size += 1 // for EOF // TODO(bill): Is this correct logic? - total: int - data = make([]byte, size, allocator) or_return - for { - n: int - n, err = read(f, data[total:]) - total += n - if err != nil { - if err == .EOF { - err = nil + if has_size { + total: int + data = make([]byte, size, allocator) or_return + for { + n: int + n, err = read(f, data[total:]) + total += n + if err != nil { + if err == .EOF { + err = nil + } + data = data[:total] + return + } + } + } else { + buffer: [1024]u8 + out_buffer := make([dynamic]u8) + total := 0 + for { + n: int = --- + n, err = read(f, buffer[:]) + total += n + append_elems(&out_buffer, ..buffer[:total]) + if err != nil { + if err == .EOF || err == .Broken_Pipe { + err = nil + } + data = out_buffer[:total] + return } - data = data[:total] - return } } } diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin index 8cb040a0a..fc3cebaea 100644 --- a/core/os/os2/file_windows.odin +++ b/core/os/os2/file_windows.odin @@ -434,6 +434,9 @@ _write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) { _file_size :: proc(f: ^File) -> (n: i64, err: Error) { length: win32.LARGE_INTEGER + if f.impl.kind == .Pipe { + return 0, .No_Size + } handle := _handle(f) if !win32.GetFileSizeEx(handle, &length) { err = _get_platform_error() @@ -766,7 +769,6 @@ _is_dir :: proc(path: string) -> bool { _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { f := (^File)(stream_data) ferr: Error - i: int switch mode { case .Read: n, ferr = _read(f, p) From c843002d07bb7d42b4c1e29801489ee7eb75edf9 Mon Sep 17 00:00:00 2001 From: flysand7 Date: Mon, 25 Mar 2024 23:35:01 +1100 Subject: [PATCH 2/3] [core/os2]: Move .Broken_Pipe to General_Error enum --- core/os/os2/errors.odin | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/core/os/os2/errors.odin b/core/os/os2/errors.odin index 77c5b1199..d76b2d549 100644 --- a/core/os/os2/errors.odin +++ b/core/os/os2/errors.odin @@ -13,6 +13,8 @@ General_Error :: enum u32 { Timeout, + Broken_Pipe, + // Indicates that an attempt to retrieve a file's size was made, but the // file doesn't have a size. No_Size, @@ -26,15 +28,9 @@ General_Error :: enum u32 { Platform_Error :: enum i32 {None=0} -Read_Error :: enum u32 { - None, - Broken_Pipe, -} - Error :: union #shared_nil { General_Error, io.Error, - Read_Error, runtime.Allocator_Error, Platform_Error, } @@ -61,6 +57,7 @@ error_string :: proc(ferr: Error) -> string { case .Not_Exist: return "file does not exist" case .Closed: return "file already closed" case .Timeout: return "i/o timeout" + case .Broken_Pipe: return "Broken pipe" case .No_Size: return "file has no definite size" case .Invalid_File: return "invalid file" case .Invalid_Dir: return "invalid directory" @@ -93,11 +90,6 @@ error_string :: proc(ferr: Error) -> string { case .Invalid_Argument: return "invalid allocator argument" case .Mode_Not_Implemented: return "allocator mode not implemented" } - case Read_Error: - switch e { - case .None: return "" - case .Broken_Pipe: return "Broken pipe" - } case Platform_Error: return _error_string(i32(e)) } From 3ee91845372ec5513812857c9ba069829eba0303 Mon Sep 17 00:00:00 2001 From: flysand7 Date: Mon, 1 Apr 2024 23:32:16 +1100 Subject: [PATCH 3/3] [core/os2]: Fix memory leak on read_entire_file --- core/os/os2/file_util.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/os/os2/file_util.odin b/core/os/os2/file_util.odin index bb3dfd9eb..0708f708e 100644 --- a/core/os/os2/file_util.odin +++ b/core/os/os2/file_util.odin @@ -117,7 +117,7 @@ read_entire_file_from_file :: proc(f: ^File, allocator: runtime.Allocator) -> (d } } else { buffer: [1024]u8 - out_buffer := make([dynamic]u8) + out_buffer := make([dynamic]u8, 0, 0, allocator) total := 0 for { n: int = ---