Browse Source

Make `os2.File` a more generic interface

gingerBill 1 year ago
parent
commit
4f73b35da5

+ 2 - 2
core/os/os2/file.odin

@@ -5,9 +5,9 @@ import "core:time"
 import "base:runtime"
 
 File :: struct {
-	impl:   _File,
+	impl:   rawptr,
 	stream: io.Stream,
-	fstat: Fstat_Callback,
+	fstat:  Fstat_Callback,
 }
 
 File_Mode :: distinct u32

+ 55 - 38
core/os/os2/file_linux.odin

@@ -7,13 +7,14 @@ import "base:runtime"
 import "core:sys/linux"
 
 _File :: struct {
+	using file: File,
 	name: string,
 	fd: linux.Fd,
 	allocator: runtime.Allocator,
 }
 
-_stdin : File = {
-	impl = {
+_stdin := File{
+	impl = &_File{
 		name = "/proc/self/fd/0",
 		fd = 0,
 		allocator = _file_allocator(),
@@ -21,9 +22,10 @@ _stdin : File = {
 	stream = {
 		procedure = _file_stream_proc,
 	},
+	fstat = _fstat,
 }
-_stdout : File = {
-	impl = {
+_stdout := File{
+	impl = &_File{
 		name = "/proc/self/fd/1",
 		fd = 1,
 		allocator = _file_allocator(),
@@ -31,9 +33,10 @@ _stdout : File = {
 	stream = {
 		procedure = _file_stream_proc,
 	},
+	fstat = _fstat,
 }
-_stderr : File = {
-	impl = {
+_stderr := File{
+	impl = &_File{
 		name = "/proc/self/fd/2",
 		fd = 2,
 		allocator = _file_allocator(),
@@ -41,6 +44,7 @@ _stderr : File = {
 	stream = {
 		procedure = _file_stream_proc,
 	},
+	fstat = _fstat,
 }
 
 @init
@@ -89,35 +93,35 @@ _open :: proc(name: string, flags: File_Flags, perm: File_Mode) -> (f: ^File, er
 }
 
 _new_file :: proc(fd: uintptr, _: string = "") -> ^File {
-	file := new(File, file_allocator())
-	file.impl = {
-		fd = linux.Fd(fd),
-		allocator = file_allocator(),
-		name = _get_full_path(file.impl.fd, file.impl.allocator),
-	}
-	file.stream = {
-		data = file,
+	impl := new(_File, file_allocator())
+	impl.fd = linux.Fd(fd)
+	impl.allocator = file_allocator()
+	impl.name = _get_full_path(impl.fd, impl.allocator)
+	impl.file.stream = {
+		data = &impl.file,
 		procedure = _file_stream_proc,
 	}
-	file.fstat = _fstat
-	return file
+	impl.fstat = _fstat
+	return impl
 }
 
 _destroy :: proc(f: ^File) -> Error {
-	if f == nil {
+	if f == nil || f.impl == nil {
 		return nil
 	}
-	delete(f.impl.name, f.impl.allocator)
-	free(f, f.impl.allocator)
+	impl := (^_File)(f.impl)
+	delete(impl.name, impl.allocator)
+	free(f, impl.allocator)
 	return nil
 }
 
 
 _close :: proc(f: ^File) -> Error {
-	if f == nil {
+	if f == nil || f.impl == nil {
 		return nil
 	}
-	errno := linux.close(f.impl.fd)
+	impl := (^_File)(f.impl)
+	errno := linux.close(impl.fd)
 	if errno == .EBADF { // avoid possible double free
 		return _get_platform_error(errno)
 	}
@@ -126,18 +130,20 @@ _close :: proc(f: ^File) -> Error {
 }
 
 _fd :: proc(f: ^File) -> uintptr {
-	if f == nil {
+	if f == nil || f.impl == nil {
 		return ~uintptr(0)
 	}
-	return uintptr(f.impl.fd)
+	impl := (^_File)(f.impl)
+	return uintptr(impl.fd)
 }
 
 _name :: proc(f: ^File) -> string {
-	return f.impl.name if f != nil else ""
+	return (^_File)(f.impl).name if f != nil && f.impl != nil else ""
 }
 
 _seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) {
-	n, errno := linux.lseek(f.impl.fd, offset, linux.Seek_Whence(whence))
+	impl := (^_File)(f.impl)
+	n, errno := linux.lseek(impl.fd, offset, linux.Seek_Whence(whence))
 	if errno != .NONE {
 		return -1, _get_platform_error(errno)
 	}
@@ -148,7 +154,8 @@ _read :: proc(f: ^File, p: []byte) -> (i64, Error) {
 	if len(p) == 0 {
 		return 0, nil
 	}
-	n, errno := linux.read(f.impl.fd, p[:])
+	impl := (^_File)(f.impl)
+	n, errno := linux.read(impl.fd, p[:])
 	if errno != .NONE {
 		return -1, _get_platform_error(errno)
 	}
@@ -159,8 +166,8 @@ _read_at :: proc(f: ^File, p: []byte, offset: i64) -> (i64, Error) {
 	if offset < 0 {
 		return 0, .Invalid_Offset
 	}
-
-	n, errno := linux.pread(f.impl.fd, p[:], offset)
+	impl := (^_File)(f.impl)
+	n, errno := linux.pread(impl.fd, p[:], offset)
 	if errno != .NONE {
 		return -1, _get_platform_error(errno)
 	}
@@ -174,7 +181,8 @@ _write :: proc(f: ^File, p: []byte) -> (i64, Error) {
 	if len(p) == 0 {
 		return 0, nil
 	}
-	n, errno := linux.write(f.impl.fd, p[:])
+	impl := (^_File)(f.impl)
+	n, errno := linux.write(impl.fd, p[:])
 	if errno != .NONE {
 		return -1, _get_platform_error(errno)
 	}
@@ -186,7 +194,8 @@ _write_at :: proc(f: ^File, p: []byte, offset: i64) -> (i64, Error) {
 		return 0, .Invalid_Offset
 	}
 
-	n, errno := linux.pwrite(f.impl.fd, p[:], offset)
+	impl := (^_File)(f.impl)
+	n, errno := linux.pwrite(impl.fd, p[:], offset)
 	if errno != .NONE {
 		return -1, _get_platform_error(errno)
 	}
@@ -195,7 +204,8 @@ _write_at :: proc(f: ^File, p: []byte, offset: i64) -> (i64, Error) {
 
 _file_size :: proc(f: ^File) -> (n: i64, err: Error) {
 	s: linux.Stat = ---
-	errno := linux.fstat(f.impl.fd, &s)
+	impl := (^_File)(f.impl)
+	errno := linux.fstat(impl.fd, &s)
 	if errno != .NONE {
 		return -1, _get_platform_error(errno)
 	}
@@ -203,15 +213,18 @@ _file_size :: proc(f: ^File) -> (n: i64, err: Error) {
 }
 
 _sync :: proc(f: ^File) -> Error {
-	return _get_platform_error(linux.fsync(f.impl.fd))
+	impl := (^_File)(f.impl)
+	return _get_platform_error(linux.fsync(impl.fd))
 }
 
 _flush :: proc(f: ^File) -> Error {
-	return _get_platform_error(linux.fsync(f.impl.fd))
+	impl := (^_File)(f.impl)
+	return _get_platform_error(linux.fsync(impl.fd))
 }
 
 _truncate :: proc(f: ^File, size: i64) -> Error {
-	return _get_platform_error(linux.ftruncate(f.impl.fd, size))
+	impl := (^_File)(f.impl)
+	return _get_platform_error(linux.ftruncate(impl.fd, size))
 }
 
 _remove :: proc(name: string) -> Error {
@@ -287,7 +300,8 @@ _chdir :: proc(name: string) -> Error {
 }
 
 _fchdir :: proc(f: ^File) -> Error {
-	return _get_platform_error(linux.fchdir(f.impl.fd))
+	impl := (^_File)(f.impl)
+	return _get_platform_error(linux.fchdir(impl.fd))
 }
 
 _chmod :: proc(name: string, mode: File_Mode) -> Error {
@@ -297,7 +311,8 @@ _chmod :: proc(name: string, mode: File_Mode) -> Error {
 }
 
 _fchmod :: proc(f: ^File, mode: File_Mode) -> Error {
-	return _get_platform_error(linux.fchmod(f.impl.fd, transmute(linux.Mode)(u32(mode))))
+	impl := (^_File)(f.impl)
+	return _get_platform_error(linux.fchmod(impl.fd, transmute(linux.Mode)(u32(mode))))
 }
 
 // NOTE: will throw error without super user priviledges
@@ -316,7 +331,8 @@ _lchown :: proc(name: string, uid, gid: int) -> Error {
 
 // NOTE: will throw error without super user priviledges
 _fchown :: proc(f: ^File, uid, gid: int) -> Error {
-	return _get_platform_error(linux.fchown(f.impl.fd, linux.Uid(uid), linux.Gid(gid)))
+	impl := (^_File)(f.impl)
+	return _get_platform_error(linux.fchown(impl.fd, linux.Uid(uid), linux.Gid(gid)))
 }
 
 _chtimes :: proc(name: string, atime, mtime: time.Time) -> Error {
@@ -346,7 +362,8 @@ _fchtimes :: proc(f: ^File, atime, mtime: time.Time) -> Error {
 			uint(mtime._nsec) % uint(time.Second),
 		},
 	}
-	return _get_platform_error(linux.utimensat(f.impl.fd, nil, &times[0], nil))
+	impl := (^_File)(f.impl)
+	return _get_platform_error(linux.utimensat(impl.fd, nil, &times[0], nil))
 }
 
 _exists :: proc(name: string) -> bool {

+ 41 - 30
core/os/os2/file_windows.odin

@@ -24,6 +24,8 @@ _File_Kind :: enum u8 {
 }
 
 _File :: struct {
+	using file: File,
+
 	fd:   rawptr,
 	name: string,
 	wname: win32.wstring,
@@ -130,12 +132,12 @@ _new_file :: proc(handle: uintptr, name: string) -> ^File {
 	if handle == INVALID_HANDLE {
 		return nil
 	}
-	f := new(File, file_allocator())
+	f := new(_File, file_allocator())
 
-	f.impl.allocator = file_allocator()
-	f.impl.fd = rawptr(handle)
-	f.impl.name, _ = clone_string(name, f.impl.allocator)
-	f.impl.wname = win32.utf8_to_wstring(name, f.impl.allocator)
+	f.allocator = file_allocator()
+	f.fd = rawptr(handle)
+	f.name, _ = clone_string(name, f.allocator)
+	f.wname = win32.utf8_to_wstring(name, f.allocator)
 
 	handle := _handle(f)
 	kind := _File_Kind.File
@@ -145,7 +147,7 @@ _new_file :: proc(handle: uintptr, name: string) -> ^File {
 	if win32.GetFileType(handle) == win32.FILE_TYPE_PIPE {
 		kind = .Pipe
 	}
-	f.impl.kind = kind
+	f.kind = kind
 
 	f.stream = {
 		data = f,
@@ -157,37 +159,38 @@ _new_file :: proc(handle: uintptr, name: string) -> ^File {
 }
 
 _fd :: proc(f: ^File) -> uintptr {
-	if f == nil {
+	if f == nil || f.impl == nil {
 		return INVALID_HANDLE
 	}
-	return uintptr(f.impl.fd)
+	return uintptr((^_File)(f.impl).fd)
 }
 
 _destroy :: proc(f: ^File) -> Error {
-	if f == nil {
+	if f == nil || f.impl == nil {
 		return nil
 	}
 
-	a := f.impl.allocator
-	free(f.impl.wname, a)
-	delete(f.impl.name, a)
-	free(f, a)
+	_f := (^_File)(f.impl)
+	a := _f.allocator
+	free(_f.wname, a)
+	delete(_f.name, a)
+	free(_f, a)
 	return nil
 }
 
 
 _close :: proc(f: ^File) -> Error {
-	if f == nil {
+	if f == nil || f.impl == nil {
 		return nil
 	}
-	if !win32.CloseHandle(win32.HANDLE(f.impl.fd)) {
+	if !win32.CloseHandle(win32.HANDLE((^_File)(f.impl).fd)) {
 		return .Closed
 	}
 	return _destroy(f)
 }
 
 _name :: proc(f: ^File) -> string {
-	return f.impl.name if f != nil else ""
+	return (^_File)(f.impl).name if f != nil && f.impl != nil else ""
 }
 
 _seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) {
@@ -195,11 +198,13 @@ _seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Er
 	if handle == win32.INVALID_HANDLE {
 		return 0, .Invalid_File
 	}
-	if f.impl.kind == .Pipe {
+	impl := (^_File)(f.impl)
+
+	if impl.kind == .Pipe {
 		return 0, .Invalid_File
 	}
 
-	sync.guard(&f.impl.rw_mutex)
+	sync.guard(&impl.rw_mutex)
 
 	w: u32
 	switch whence {
@@ -274,12 +279,13 @@ _read :: proc(f: ^File, p: []byte) -> (n: i64, err: Error) {
 	total_read: int
 	length := len(p)
 
-	sync.shared_guard(&f.impl.rw_mutex) // multiple readers
+	impl := (^_File)(f.impl)
+	sync.shared_guard(&impl.rw_mutex) // multiple readers
 
-	if sync.guard(&f.impl.p_mutex) {
+	if sync.guard(&impl.p_mutex) {
 		to_read := min(win32.DWORD(length), MAX_RW)
 		ok: win32.BOOL
-		if f.impl.kind == .Console {
+		if impl.kind == .Console {
 			n, cerr := read_console(handle, p[total_read:][:to_read])
 			total_read += n
 			if cerr != nil {
@@ -326,7 +332,8 @@ _read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) {
 		return
 	}
 
-	sync.guard(&f.impl.p_mutex)
+	impl := (^_File)(f.impl)
+	sync.guard(&impl.p_mutex)
 
 	p, offset := p, offset
 	for len(p) > 0 {
@@ -349,7 +356,8 @@ _write :: proc(f: ^File, p: []byte) -> (n: i64, err: Error) {
 
 	handle := _handle(f)
 
-	sync.guard(&f.impl.rw_mutex)
+	impl := (^_File)(f.impl)
+	sync.guard(&impl.rw_mutex)
 	for total_write < length {
 		remaining := length - total_write
 		to_write := win32.DWORD(min(i32(remaining), MAX_RW))
@@ -390,7 +398,8 @@ _write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) {
 		return
 	}
 
-	sync.guard(&f.impl.p_mutex)
+	impl := (^_File)(f.impl)
+	sync.guard(&impl.p_mutex)
 	p, offset := p, offset
 	for len(p) > 0 {
 		m := pwrite(f, p, offset) or_return
@@ -403,7 +412,8 @@ _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 {
+	impl := (^_File)(f.impl)
+	if impl.kind == .Pipe {
 		return 0, .No_Size
 	}
 	handle := _handle(f)
@@ -428,7 +438,7 @@ _flush :: proc(f: ^File) -> Error {
 }
 
 _truncate :: proc(f: ^File, size: i64) -> Error {
-	if f == nil {
+	if f == nil || f.impl == nil {
 		return nil
 	}
 	curr_off := seek(f, 0, .Current) or_return
@@ -615,17 +625,18 @@ _read_link :: proc(name: string, allocator: runtime.Allocator) -> (s: string, er
 
 
 _fchdir :: proc(f: ^File) -> Error {
-	if f == nil {
+	if f == nil || f.impl == nil {
 		return nil
 	}
-	if !win32.SetCurrentDirectoryW(f.impl.wname) {
+	impl := (^_File)(f.impl)
+	if !win32.SetCurrentDirectoryW(impl.wname) {
 		return _get_platform_error()
 	}
 	return nil
 }
 
 _fchmod :: proc(f: ^File, mode: File_Mode) -> Error {
-	if f == nil {
+	if f == nil || f.impl == nil {
 		return nil
 	}
 	d: win32.BY_HANDLE_FILE_INFORMATION
@@ -680,7 +691,7 @@ _chtimes :: proc(name: string, atime, mtime: time.Time) -> Error {
 	return _fchtimes(f, atime, mtime)
 }
 _fchtimes :: proc(f: ^File, atime, mtime: time.Time) -> Error {
-	if f == nil {
+	if f == nil || f.impl == nil {
 		return nil
 	}
 	d: win32.BY_HANDLE_FILE_INFORMATION

+ 2 - 1
core/os/os2/stat_linux.odin

@@ -7,7 +7,8 @@ import "core:sys/linux"
 import "core:path/filepath"
 
 _fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) {
-	return _fstat_internal(f.impl.fd, allocator)
+	impl := (^_File)(f.impl)
+	return _fstat_internal(impl.fd, allocator)
 }
 
 _fstat_internal :: proc(fd: linux.Fd, allocator: runtime.Allocator) -> (File_Info, Error) {

+ 3 - 3
core/os/os2/stat_windows.odin

@@ -7,7 +7,7 @@ import "core:strings"
 import win32 "core:sys/windows"
 
 _fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) {
-	if f == nil || f.impl.fd == nil {
+	if f == nil || (^_File)(f.impl).fd == nil {
 		return {}, nil
 	}
 
@@ -122,7 +122,7 @@ _cleanpath_strip_prefix :: proc(buf: []u16) -> []u16 {
 
 
 _cleanpath_from_handle :: proc(f: ^File, allocator: runtime.Allocator) -> (string, Error) {
-	if f == nil || f.impl.fd == nil {
+	if f == nil || (^_File)(f.impl).fd == nil {
 		return "", nil
 	}
 	h := _handle(f)
@@ -138,7 +138,7 @@ _cleanpath_from_handle :: proc(f: ^File, allocator: runtime.Allocator) -> (strin
 }
 
 _cleanpath_from_handle_u16 :: proc(f: ^File) -> ([]u16, Error) {
-	if f == nil || f.impl.fd == nil {
+	if f == nil || (^_File)(f.impl).fd == nil {
 		return nil, nil
 	}
 	h := _handle(f)