Go to a File based approach over Handle based

This commit is contained in:
gingerBill
2022-05-05 16:15:03 +01:00
parent e61aad925b
commit 18bde22b26
12 changed files with 185 additions and 167 deletions

View File

@@ -1,7 +1,6 @@
//+private
package os2
import "core:mem"
import win32 "core:sys/windows"
_lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) {
@@ -9,24 +8,28 @@ _lookup_env :: proc(key: string, allocator := context.allocator) -> (value: stri
return
}
wkey := win32.utf8_to_wstring(key)
b := make([dynamic]u16, 100, context.temp_allocator)
for {
n := win32.GetEnvironmentVariableW(wkey, raw_data(b), u32(len(b)))
if n == 0 {
err := win32.GetLastError()
if err == win32.ERROR_ENVVAR_NOT_FOUND {
return "", false
}
}
if n <= u32(len(b)) {
value = win32.utf16_to_utf8(b[:n], allocator)
found = true
return
n := win32.GetEnvironmentVariableW(wkey, nil, 0)
if n == 0 {
err := win32.GetLastError()
if err == win32.ERROR_ENVVAR_NOT_FOUND {
return "", false
}
resize(&b, len(b)*2)
return "", true
}
b := make([]u16, n+1, context.temp_allocator)
n = win32.GetEnvironmentVariableW(wkey, raw_data(b), u32(len(b)))
if n == 0 {
err := win32.GetLastError()
if err == win32.ERROR_ENVVAR_NOT_FOUND {
return "", false
}
}
value = win32.utf16_to_utf8(b[:n], allocator)
found = true
return
}
_set_env :: proc(key, value: string) -> bool {
@@ -62,13 +65,12 @@ _environ :: proc(allocator := context.allocator) -> []string {
r := make([dynamic]string, 0, 50, allocator)
for from, i, p := 0, 0, envs; true; i += 1 {
c := (^u16)(uintptr(p) + uintptr(i*2))^
c := ([^]u16)(p)[i]
if c == 0 {
if i <= from {
break
}
w := mem.slice_ptr(mem.ptr_offset(p, from), i-from)
w := ([^]u16)(p)[from:i]
append(&r, win32.utf16_to_utf8(w, allocator))
from = i + 1
}

View File

@@ -3,7 +3,9 @@ package os2
import "core:io"
import "core:time"
Handle :: distinct uintptr
File :: struct {
impl: _File,
}
Seek_From :: enum {
Start = 0, // seek relative to the origin of the file
@@ -30,74 +32,79 @@ O_TRUNC :: int(64)
stdin: Handle = 0 // OS-Specific
stdout: Handle = 1 // OS-Specific
stderr: Handle = 2 // OS-Specific
stdin: ^File = nil // OS-Specific
stdout: ^File = nil // OS-Specific
stderr: ^File = nil // OS-Specific
create :: proc(name: string) -> (Handle, Error) {
create :: proc(name: string) -> (^File, Error) {
return _create(name)
}
open :: proc(name: string) -> (Handle, Error) {
open :: proc(name: string) -> (^File, Error) {
return _open(name)
}
open_file :: proc(name: string, flag: int, perm: File_Mode) -> (Handle, Error) {
open_file :: proc(name: string, flag: int, perm: File_Mode) -> (^File, Error) {
return _open_file(name, flag, perm)
}
close :: proc(fd: Handle) -> Error {
return _close(fd)
}
name :: proc(fd: Handle, allocator := context.allocator) -> string {
return _name(fd)
}
seek :: proc(fd: Handle, offset: i64, whence: Seek_From) -> (ret: i64, err: Error) {
return _seek(fd, offset, whence)
}
read :: proc(fd: Handle, p: []byte) -> (n: int, err: Error) {
return _read(fd, p)
}
read_at :: proc(fd: Handle, p: []byte, offset: i64) -> (n: int, err: Error) {
return _read_at(fd, p, offset)
}
read_from :: proc(fd: Handle, r: io.Reader) -> (n: i64, err: Error) {
return _read_from(fd, r)
}
write :: proc(fd: Handle, p: []byte) -> (n: int, err: Error) {
return _write(fd, p)
}
write_at :: proc(fd: Handle, p: []byte, offset: i64) -> (n: int, err: Error) {
return _write_at(fd, p, offset)
}
write_to :: proc(fd: Handle, w: io.Writer) -> (n: i64, err: Error) {
return _write_to(fd, w)
}
file_size :: proc(fd: Handle) -> (n: i64, err: Error) {
return _file_size(fd)
new_file :: proc(handle: uintptr, name: string) -> ^File {
return _new_file(handle, name)
}
sync :: proc(fd: Handle) -> Error {
return _sync(fd)
close :: proc(f: ^File) -> Error {
return _close(f)
}
flush :: proc(fd: Handle) -> Error {
return _flush(fd)
name :: proc(f: ^File, allocator := context.allocator) -> string {
return _name(f)
}
truncate :: proc(fd: Handle, size: i64) -> Maybe(Path_Error) {
return _truncate(fd, size)
seek :: proc(f: ^File, offset: i64, whence: Seek_From) -> (ret: i64, err: Error) {
return _seek(f, offset, whence)
}
read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
return _read(f, p)
}
read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
return _read_at(f, p, offset)
}
read_from :: proc(f: ^File, r: io.Reader) -> (n: i64, err: Error) {
return _read_from(f, r)
}
write :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
return _write(f, p)
}
write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
return _write_at(f, p, offset)
}
write_to :: proc(f: ^File, w: io.Writer) -> (n: i64, err: Error) {
return _write_to(f, w)
}
file_size :: proc(f: ^File) -> (n: i64, err: Error) {
return _file_size(f)
}
sync :: proc(f: ^File) -> Error {
return _sync(f)
}
flush :: proc(f: ^File) -> Error {
return _flush(f)
}
truncate :: proc(f: ^File, size: i64) -> Maybe(Path_Error) {
return _truncate(f, size)
}
remove :: proc(name: string) -> Maybe(Path_Error) {
@@ -122,16 +129,16 @@ read_link :: proc(name: string) -> (string, Maybe(Path_Error)) {
}
chdir :: proc(fd: Handle) -> Error {
return _chdir(fd)
chdir :: proc(f: ^File) -> Error {
return _chdir(f)
}
chmod :: proc(fd: Handle, mode: File_Mode) -> Error {
return _chmod(fd, mode)
chmod :: proc(f: ^File, mode: File_Mode) -> Error {
return _chmod(f, mode)
}
chown :: proc(fd: Handle, uid, gid: int) -> Error {
return _chown(fd, uid, gid)
chown :: proc(f: ^File, uid, gid: int) -> Error {
return _chown(f, uid, gid)
}

View File

@@ -2,8 +2,8 @@ package os2
import "core:io"
file_to_stream :: proc(fd: Handle) -> (s: io.Stream) {
s.stream_data = rawptr(uintptr(fd))
file_to_stream :: proc(f: ^File) -> (s: io.Stream) {
s.stream_data = f
s.stream_vtable = _file_stream_vtable
return
}
@@ -20,66 +20,66 @@ error_to_io_error :: proc(ferr: Error) -> io.Error {
@(private)
_file_stream_vtable := &io.Stream_VTable{
impl_read = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
fd := Handle(uintptr(s.stream_data))
f := (^File)(s.stream_data)
ferr: Error
n, ferr = read(fd, p)
n, ferr = read(f, p)
err = error_to_io_error(ferr)
return
},
impl_read_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) {
fd := Handle(uintptr(s.stream_data))
f := (^File)(s.stream_data)
ferr: Error
n, ferr = read_at(fd, p, offset)
n, ferr = read_at(f, p, offset)
err = error_to_io_error(ferr)
return
},
impl_write_to = proc(s: io.Stream, w: io.Writer) -> (n: i64, err: io.Error) {
fd := Handle(uintptr(s.stream_data))
f := (^File)(s.stream_data)
ferr: Error
n, ferr = write_to(fd, w)
n, ferr = write_to(f, w)
err = error_to_io_error(ferr)
return
},
impl_write = proc(s: io.Stream, p: []byte) -> (n: int, err: io.Error) {
fd := Handle(uintptr(s.stream_data))
f := (^File)(s.stream_data)
ferr: Error
n, ferr = write(fd, p)
n, ferr = write(f, p)
err = error_to_io_error(ferr)
return
},
impl_write_at = proc(s: io.Stream, p: []byte, offset: i64) -> (n: int, err: io.Error) {
fd := Handle(uintptr(s.stream_data))
f := (^File)(s.stream_data)
ferr: Error
n, ferr = write_at(fd, p, offset)
n, ferr = write_at(f, p, offset)
err = error_to_io_error(ferr)
return
},
impl_read_from = proc(s: io.Stream, r: io.Reader) -> (n: i64, err: io.Error) {
fd := Handle(uintptr(s.stream_data))
f := (^File)(s.stream_data)
ferr: Error
n, ferr = read_from(fd, r)
n, ferr = read_from(f, r)
err = error_to_io_error(ferr)
return
},
impl_seek = proc(s: io.Stream, offset: i64, whence: io.Seek_From) -> (i64, io.Error) {
fd := Handle(uintptr(s.stream_data))
n, ferr := seek(fd, offset, Seek_From(whence))
f := (^File)(s.stream_data)
n, ferr := seek(f, offset, Seek_From(whence))
err := error_to_io_error(ferr)
return n, err
},
impl_size = proc(s: io.Stream) -> i64 {
fd := Handle(uintptr(s.stream_data))
sz, _ := file_size(fd)
f := (^File)(s.stream_data)
sz, _ := file_size(f)
return sz
},
impl_flush = proc(s: io.Stream) -> io.Error {
fd := Handle(uintptr(s.stream_data))
ferr := flush(fd)
f := (^File)(s.stream_data)
ferr := flush(f)
return error_to_io_error(ferr)
},
impl_close = proc(s: io.Stream) -> io.Error {
fd := Handle(uintptr(s.stream_data))
ferr := close(fd)
f := (^File)(s.stream_data)
ferr := close(f)
return error_to_io_error(ferr)
},
}

View File

@@ -4,25 +4,25 @@ import "core:mem"
import "core:strconv"
import "core:unicode/utf8"
write_string :: proc(fd: Handle, s: string) -> (n: int, err: Error) {
return write(fd, transmute([]byte)s)
write_string :: proc(f: ^File, s: string) -> (n: int, err: Error) {
return write(f, transmute([]byte)s)
}
write_byte :: proc(fd: Handle, b: byte) -> (n: int, err: Error) {
return write(fd, []byte{b})
write_byte :: proc(f: ^File, b: byte) -> (n: int, err: Error) {
return write(f, []byte{b})
}
write_rune :: proc(fd: Handle, r: rune) -> (n: int, err: Error) {
write_rune :: proc(f: ^File, r: rune) -> (n: int, err: Error) {
if r < utf8.RUNE_SELF {
return write_byte(fd, byte(r))
return write_byte(f, byte(r))
}
b: [4]byte
b, n = utf8.encode_rune(r)
return write(fd, b[:n])
return write(f, b[:n])
}
write_encoded_rune :: proc(fd: Handle, r: rune) -> (n: int, err: Error) {
write_encoded_rune :: proc(f: ^File, r: rune) -> (n: int, err: Error) {
wrap :: proc(m: int, merr: Error, n: ^int, err: ^Error) -> bool {
n^ += m
if merr != nil {
@@ -32,44 +32,44 @@ write_encoded_rune :: proc(fd: Handle, r: rune) -> (n: int, err: Error) {
return false
}
if wrap(write_byte(fd, '\''), &n, &err) { return }
if wrap(write_byte(f, '\''), &n, &err) { return }
switch r {
case '\a': if wrap(write_string(fd, "\\a"), &n, &err) { return }
case '\b': if wrap(write_string(fd, "\\b"), &n, &err) { return }
case '\e': if wrap(write_string(fd, "\\e"), &n, &err) { return }
case '\f': if wrap(write_string(fd, "\\f"), &n, &err) { return }
case '\n': if wrap(write_string(fd, "\\n"), &n, &err) { return }
case '\r': if wrap(write_string(fd, "\\r"), &n, &err) { return }
case '\t': if wrap(write_string(fd, "\\t"), &n, &err) { return }
case '\v': if wrap(write_string(fd, "\\v"), &n, &err) { return }
case '\a': if wrap(write_string(f, "\\a"), &n, &err) { return }
case '\b': if wrap(write_string(f, "\\b"), &n, &err) { return }
case '\e': if wrap(write_string(f, "\\e"), &n, &err) { return }
case '\f': if wrap(write_string(f, "\\f"), &n, &err) { return }
case '\n': if wrap(write_string(f, "\\n"), &n, &err) { return }
case '\r': if wrap(write_string(f, "\\r"), &n, &err) { return }
case '\t': if wrap(write_string(f, "\\t"), &n, &err) { return }
case '\v': if wrap(write_string(f, "\\v"), &n, &err) { return }
case:
if r < 32 {
if wrap(write_string(fd, "\\x"), &n, &err) { return }
if wrap(write_string(f, "\\x"), &n, &err) { return }
b: [2]byte
s := strconv.append_bits(b[:], u64(r), 16, true, 64, strconv.digits, nil)
switch len(s) {
case 0: if wrap(write_string(fd, "00"), &n, &err) { return }
case 1: if wrap(write_rune(fd, '0'), &n, &err) { return }
case 2: if wrap(write_string(fd, s), &n, &err) { return }
case 0: if wrap(write_string(f, "00"), &n, &err) { return }
case 1: if wrap(write_rune(f, '0'), &n, &err) { return }
case 2: if wrap(write_string(f, s), &n, &err) { return }
}
} else {
if wrap(write_rune(fd, r), &n, &err) { return }
if wrap(write_rune(f, r), &n, &err) { return }
}
}
_ = wrap(write_byte(fd, '\''), &n, &err)
_ = wrap(write_byte(f, '\''), &n, &err)
return
}
write_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (n: int, err: Error) {
write_ptr :: proc(f: ^File, data: rawptr, len: int) -> (n: int, err: Error) {
s := transmute([]byte)mem.Raw_Slice{data, len}
return write(fd, s)
return write(f, s)
}
read_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (n: int, err: Error) {
read_ptr :: proc(f: ^File, data: rawptr, len: int) -> (n: int, err: Error) {
s := transmute([]byte)mem.Raw_Slice{data, len}
return read(fd, s)
return read(f, s)
}

View File

@@ -4,68 +4,77 @@ package os2
import "core:io"
import "core:time"
_create :: proc(name: string) -> (Handle, Error) {
return 0, nil
_File :: struct {
fd: rawptr,
name: string,
}
_open :: proc(name: string) -> (Handle, Error) {
return 0, nil
_create :: proc(name: string) -> (^File, Error) {
return nil, nil
}
_open_file :: proc(name: string, flag: int, perm: File_Mode) -> (Handle, Error) {
return 0, nil
_open :: proc(name: string) -> (^File, Error) {
return nil, nil
}
_close :: proc(fd: Handle) -> Error {
_open_file :: proc(name: string, flag: int, perm: File_Mode) -> (^File, Error) {
return nil, nil
}
_new_file :: proc(handle: uintptr, name: string) -> ^File {
return nil
}
_name :: proc(fd: Handle, allocator := context.allocator) -> string {
_close :: proc(f: ^File) -> Error {
return nil
}
_name :: proc(f: ^File, allocator := context.allocator) -> string {
return ""
}
_seek :: proc(fd: Handle, offset: i64, whence: Seek_From) -> (ret: i64, err: Error) {
_seek :: proc(f: ^File, offset: i64, whence: Seek_From) -> (ret: i64, err: Error) {
return
}
_read :: proc(fd: Handle, p: []byte) -> (n: int, err: Error) {
_read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
return
}
_read_at :: proc(fd: Handle, p: []byte, offset: i64) -> (n: int, err: Error) {
_read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
return
}
_read_from :: proc(fd: Handle, r: io.Reader) -> (n: i64, err: Error) {
_read_from :: proc(f: ^File, r: io.Reader) -> (n: i64, err: Error) {
return
}
_write :: proc(fd: Handle, p: []byte) -> (n: int, err: Error) {
_write :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
return
}
_write_at :: proc(fd: Handle, p: []byte, offset: i64) -> (n: int, err: Error) {
_write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
return
}
_write_to :: proc(fd: Handle, w: io.Writer) -> (n: i64, err: Error) {
_write_to :: proc(f: ^File, w: io.Writer) -> (n: i64, err: Error) {
return
}
_file_size :: proc(fd: Handle) -> (n: i64, err: Error) {
_file_size :: proc(f: ^File) -> (n: i64, err: Error) {
return
}
_sync :: proc(fd: Handle) -> Error {
_sync :: proc(f: ^File) -> Error {
return nil
}
_flush :: proc(fd: Handle) -> Error {
_flush :: proc(f: ^File) -> Error {
return nil
}
_truncate :: proc(fd: Handle, size: i64) -> Maybe(Path_Error) {
_truncate :: proc(f: ^File, size: i64) -> Maybe(Path_Error) {
return nil
}
@@ -91,15 +100,15 @@ _read_link :: proc(name: string) -> (string, Maybe(Path_Error)) {
}
_chdir :: proc(fd: Handle) -> Error {
_chdir :: proc(f: ^File) -> Error {
return nil
}
_chmod :: proc(fd: Handle, mode: File_Mode) -> Error {
_chmod :: proc(f: ^File, mode: File_Mode) -> Error {
return nil
}
_chown :: proc(fd: Handle, uid, gid: int) -> Error {
_chown :: proc(f: ^File, uid, gid: int) -> Error {
return nil
}

View File

@@ -1,5 +1,5 @@
package os2
pipe :: proc() -> (r, w: Handle, err: Error) {
pipe :: proc() -> (r, w: ^File, err: Error) {
return _pipe()
}

View File

@@ -3,11 +3,11 @@ package os2
import win32 "core:sys/windows"
_pipe :: proc() -> (r, w: Handle, err: Error) {
_pipe :: proc() -> (r, w: ^File, err: Error) {
p: [2]win32.HANDLE
if !win32.CreatePipe(&p[0], &p[1], nil, 0) {
return 0, 0, Platform_Error{i32(win32.GetLastError())}
return nil, nil, Platform_Error{i32(win32.GetLastError())}
}
return Handle(p[0]), Handle(p[1]), nil
return new_file(uintptr(p[0]), ""), new_file(uintptr(p[1]), ""), nil
}

View File

@@ -46,7 +46,7 @@ Process :: struct {
Process_Attributes :: struct {
dir: string,
env: []string,
files: []Handle,
files: []^File,
sys: ^Process_Attributes_OS_Specific,
}

View File

@@ -24,8 +24,8 @@ file_info_delete :: proc(fi: File_Info, allocator := context.allocator) {
delete(fi.fullpath, allocator)
}
fstat :: proc(fd: Handle, allocator := context.allocator) -> (File_Info, Maybe(Path_Error)) {
return _fstat(fd, allocator)
fstat :: proc(f: ^File, allocator := context.allocator) -> (File_Info, Maybe(Path_Error)) {
return _fstat(f, allocator)
}
stat :: proc(name: string, allocator := context.allocator) -> (File_Info, Maybe(Path_Error)) {

View File

@@ -4,18 +4,18 @@ package os2
import "core:time"
import win32 "core:sys/windows"
_fstat :: proc(fd: Handle, allocator := context.allocator) -> (File_Info, Maybe(Path_Error)) {
if fd == 0 {
_fstat :: proc(f: ^File, allocator := context.allocator) -> (File_Info, Maybe(Path_Error)) {
if f == nil || f.impl.fd == nil {
return {}, Path_Error{err = .Invalid_Argument}
}
context.allocator = allocator
path, err := _cleanpath_from_handle(fd)
path, err := _cleanpath_from_handle(f)
if err != nil {
return {}, err
}
h := win32.HANDLE(fd)
h := win32.HANDLE(f.impl.fd)
switch win32.GetFileType(h) {
case win32.FILE_TYPE_PIPE, win32.FILE_TYPE_CHAR:
fi: File_Info
@@ -130,11 +130,11 @@ _cleanpath_strip_prefix :: proc(buf: []u16) -> []u16 {
}
_cleanpath_from_handle :: proc(fd: Handle) -> (string, Maybe(Path_Error)) {
if fd == 0 {
_cleanpath_from_handle :: proc(f: ^File) -> (string, Maybe(Path_Error)) {
if f == nil || f.impl.fd == nil {
return "", Path_Error{err = .Invalid_Argument}
}
h := win32.HANDLE(fd)
h := win32.HANDLE(f.impl.fd)
MAX_PATH := win32.DWORD(260) + 1
buf: []u16
@@ -153,11 +153,11 @@ _cleanpath_from_handle :: proc(fd: Handle) -> (string, Maybe(Path_Error)) {
return _cleanpath_from_buf(buf), nil
}
_cleanpath_from_handle_u16 :: proc(fd: Handle) -> ([]u16, Maybe(Path_Error)) {
if fd == 0 {
_cleanpath_from_handle_u16 :: proc(f: ^File) -> ([]u16, Maybe(Path_Error)) {
if f == nil || f.impl.fd == nil {
return nil, Path_Error{err = .Invalid_Argument}
}
h := win32.HANDLE(fd)
h := win32.HANDLE(f.impl.fd)
MAX_PATH := win32.DWORD(260) + 1
buf: []u16

View File

@@ -1,7 +1,7 @@
package os2
create_temp :: proc(dir, pattern: string) -> (Handle, Error) {
create_temp :: proc(dir, pattern: string) -> (^File, Error) {
return _create_temp(dir, pattern)
}

View File

@@ -3,8 +3,8 @@ package os2
import win32 "core:sys/windows"
_create_temp :: proc(dir, pattern: string) -> (Handle, Error) {
return 0, nil
_create_temp :: proc(dir, pattern: string) -> (^File, Error) {
return nil, nil
}
_mkdir_temp :: proc(dir, pattern: string, allocator := context.allocator) -> (string, Error) {