Browse Source

Mock out `open_buffered`

gingerBill 1 year ago
parent
commit
046f72befd
3 changed files with 150 additions and 10 deletions
  1. 9 0
      core/os/os2/file.odin
  2. 72 10
      core/os/os2/file_linux.odin
  3. 69 0
      core/os/os2/file_windows.odin

+ 9 - 0
core/os/os2/file.odin

@@ -104,6 +104,15 @@ open :: proc(name: string, flags := File_Flags{.Read}, perm := 0o777) -> (^File,
 	return _open(name, flags, perm)
 }
 
+@(require_results)
+open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm := 0o777) -> (^File, Error) {
+	if buffer_size == 0 {
+		return _open(name, flags, perm)
+	}
+	return _open_buffered(name, buffer_size, flags, perm)
+}
+
+
 @(require_results)
 new_file :: proc(handle: uintptr, name: string) -> ^File {
 	return _new_file(handle, name) or_else panic("Out of memory")

+ 72 - 10
core/os/os2/file_linux.odin

@@ -1,9 +1,10 @@
 //+private
 package os2
 
+import "base:runtime"
 import "core:io"
 import "core:time"
-import "base:runtime"
+import "core:sync"
 import "core:sys/linux"
 
 File_Impl :: struct {
@@ -11,13 +12,17 @@ File_Impl :: struct {
 	name: string,
 	fd: linux.Fd,
 	allocator: runtime.Allocator,
+
+	buffer:   []byte,
+	rw_mutex: sync.RW_Mutex, // read write calls
+	p_mutex:  sync.Mutex, // pread pwrite calls
 }
 
 _stdin := File{
 	impl = &File_Impl{
 		name = "/proc/self/fd/0",
 		fd = 0,
-		allocator = _file_allocator(),
+		allocator = file_allocator(),
 	},
 	stream = {
 		procedure = _file_stream_proc,
@@ -28,7 +33,7 @@ _stdout := File{
 	impl = &File_Impl{
 		name = "/proc/self/fd/1",
 		fd = 1,
-		allocator = _file_allocator(),
+		allocator = file_allocator(),
 	},
 	stream = {
 		procedure = _file_stream_proc,
@@ -39,7 +44,7 @@ _stderr := File{
 	impl = &File_Impl{
 		name = "/proc/self/fd/2",
 		fd = 2,
-		allocator = _file_allocator(),
+		allocator = file_allocator(),
 	},
 	stream = {
 		procedure = _file_stream_proc,
@@ -59,10 +64,6 @@ _standard_stream_init :: proc() {
 	stderr = &_stderr
 }
 
-_file_allocator :: proc() -> runtime.Allocator {
-	return heap_allocator()
-}
-
 _open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) {
 	TEMP_ALLOCATOR_GUARD()
 	name_cstr := temp_cstring(name) or_return
@@ -108,13 +109,30 @@ _new_file :: proc(fd: uintptr, _: string = "") -> (f: ^File, err: Error) {
 	return &impl.file, nil
 }
 
+
+@(require_results)
+_open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm := 0o777) -> (f: ^File, err: Error) {
+	assert(buffer_size > 0)
+	f, err = _open(name, flags, perm)
+	if f != nil && err == nil {
+		impl := (^File_Impl)(f.impl)
+		impl.buffer = make([]byte, buffer_size, file_allocator())
+		f.stream.procedure = _file_stream_buffered_proc
+	}
+	return
+}
+
 _destroy :: proc(f: ^File_Impl) -> Error {
 	if f == nil {
 		return nil
 	}
 	a := f.allocator
-	delete(f.name, a)
-	free(f, a)
+	err0 := delete(f.name, a)
+	err1 := delete(f.buffer, a)
+	err2 := free(f, a)
+	err0 or_return
+	err1 or_return
+	err2 or_return
 	return nil
 }
 
@@ -463,3 +481,47 @@ _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte,
 	return 0, .Empty
 }
 
+
+@(private="package")
+_file_stream_buffered_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
+	f := (^File_Impl)(stream_data)
+	ferr: Error
+	switch mode {
+	case .Read:
+		n, ferr = _read(f, p)
+		err = error_to_io_error(ferr)
+		return
+	case .Read_At:
+		n, ferr = _read_at(f, p, offset)
+		err = error_to_io_error(ferr)
+		return
+	case .Write:
+		n, ferr = _write(f, p)
+		err = error_to_io_error(ferr)
+		return
+	case .Write_At:
+		n, ferr = _write_at(f, p, offset)
+		err = error_to_io_error(ferr)
+		return
+	case .Seek:
+		n, ferr = _seek(f, offset, whence)
+		err = error_to_io_error(ferr)
+		return
+	case .Size:
+		n, ferr = _file_size(f)
+		err = error_to_io_error(ferr)
+		return
+	case .Flush:
+		ferr = _flush(f)
+		err = error_to_io_error(ferr)
+		return
+	case .Close, .Destroy:
+		ferr = _close(f)
+		err = error_to_io_error(ferr)
+		return
+	case .Query:
+		return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Flush, .Close, .Destroy, .Query})
+	}
+	return 0, .Empty
+}
+

+ 69 - 0
core/os/os2/file_windows.odin

@@ -33,6 +33,7 @@ File_Impl :: struct {
 
 	allocator: runtime.Allocator,
 
+	buffer: []byte,
 	rw_mutex: sync.RW_Mutex, // read write calls
 	p_mutex:  sync.Mutex, // pread pwrite calls
 }
@@ -165,6 +166,26 @@ _new_file :: proc(handle: uintptr, name: string) -> (f: ^File, err: Error) {
 	return &impl.file, nil
 }
 
+
+@(require_results)
+_open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm := 0o777) -> (f: ^File, err: Error) {
+	assert(buffer_size > 0)
+	flags := flags if flags != nil else {.Read}
+	handle := _open_internal(name, flags, perm) or_return
+	return _new_file_buffered(handle, name, buffer_size)
+}
+
+_new_file_buffered :: proc(handle: uintptr, name: string, buffer_size: uint) -> (f: ^File, err: Error) {
+	f, err = _new_file(handle, name)
+	if f != nil && err == nil {
+		impl := (^File_Impl)(f.impl)
+		impl.buffer = make([]byte, buffer_size, file_allocator())
+		f.stream.procedure = _file_stream_buffered_proc
+	}
+	return
+}
+
+
 _fd :: proc(f: ^File) -> uintptr {
 	if f == nil || f.impl == nil {
 		return INVALID_HANDLE
@@ -181,9 +202,11 @@ _destroy :: proc(f: ^File_Impl) -> Error {
 	err0 := free(f.wname, a)
 	err1 := delete(f.name, a)
 	err2 := free(f, a)
+	err3 := delete(f.buffer, a)
 	err0 or_return
 	err1 or_return
 	err2 or_return
+	err3 or_return
 	return nil
 }
 
@@ -780,6 +803,52 @@ _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte,
 }
 
 
+@(private="package")
+_file_stream_buffered_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) {
+	f := (^File_Impl)(stream_data)
+	ferr: Error
+	switch mode {
+	case .Read:
+		n, ferr = _read(f, p)
+		err = error_to_io_error(ferr)
+		return
+	case .Read_At:
+		n, ferr = _read_at(f, p, offset)
+		err = error_to_io_error(ferr)
+		return
+	case .Write:
+		n, ferr = _write(f, p)
+		err = error_to_io_error(ferr)
+		return
+	case .Write_At:
+		n, ferr = _write_at(f, p, offset)
+		err = error_to_io_error(ferr)
+		return
+	case .Seek:
+		n, ferr = _seek(f, offset, whence)
+		err = error_to_io_error(ferr)
+		return
+	case .Size:
+		n, ferr = _file_size(f)
+		err = error_to_io_error(ferr)
+		return
+	case .Flush:
+		ferr = _flush(f)
+		err = error_to_io_error(ferr)
+		return
+	case .Close, .Destroy:
+		ferr = _close(f)
+		err = error_to_io_error(ferr)
+		return
+	case .Query:
+		return io.query_utility({.Read, .Read_At, .Write, .Write_At, .Seek, .Size, .Flush, .Close, .Query})
+	}
+	return 0, .Empty
+}
+
+
+
+
 
 @(private="package", require_results)
 win32_utf8_to_wstring :: proc(s: string, allocator: runtime.Allocator) -> (ws: [^]u16, err: runtime.Allocator_Error) {