mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-24 14:45:00 -07:00
111 lines
2.3 KiB
Odin
111 lines
2.3 KiB
Odin
#+private
|
|
package os2
|
|
|
|
import "base:intrinsics"
|
|
import "core:sys/wasm/wasi"
|
|
|
|
Read_Directory_Iterator_Impl :: struct {
|
|
fullpath: [dynamic]byte,
|
|
buf: []byte,
|
|
off: int,
|
|
idx: int,
|
|
}
|
|
|
|
@(require_results)
|
|
_read_directory_iterator :: proc(it: ^Read_Directory_Iterator) -> (fi: File_Info, index: int, ok: bool) {
|
|
fimpl := (^File_Impl)(it.f.impl)
|
|
|
|
buf := it.impl.buf[it.impl.off:]
|
|
|
|
index = it.impl.idx
|
|
it.impl.idx += 1
|
|
|
|
for {
|
|
if len(buf) < size_of(wasi.dirent_t) {
|
|
return
|
|
}
|
|
|
|
entry := intrinsics.unaligned_load((^wasi.dirent_t)(raw_data(buf)))
|
|
buf = buf[size_of(wasi.dirent_t):]
|
|
|
|
if len(buf) < int(entry.d_namlen) {
|
|
// shouldn't be possible.
|
|
return
|
|
}
|
|
|
|
name := string(buf[:entry.d_namlen])
|
|
buf = buf[entry.d_namlen:]
|
|
it.impl.off += size_of(wasi.dirent_t) + int(entry.d_namlen)
|
|
|
|
if name == "." || name == ".." {
|
|
continue
|
|
}
|
|
|
|
n := len(fimpl.name)+1
|
|
if alloc_err := non_zero_resize(&it.impl.fullpath, n+len(name)); alloc_err != nil {
|
|
// Can't really tell caller we had an error, sad.
|
|
return
|
|
}
|
|
copy(it.impl.fullpath[n:], name)
|
|
|
|
stat, err := wasi.path_filestat_get(__fd(it.f), {}, name)
|
|
if err != nil {
|
|
// Can't stat, fill what we have from dirent.
|
|
stat = {
|
|
ino = entry.d_ino,
|
|
filetype = entry.d_type,
|
|
}
|
|
}
|
|
|
|
fi = internal_stat(stat, string(it.impl.fullpath[:]))
|
|
ok = true
|
|
return
|
|
}
|
|
}
|
|
|
|
@(require_results)
|
|
_read_directory_iterator_create :: proc(f: ^File) -> (iter: Read_Directory_Iterator, err: Error) {
|
|
if f == nil || f.impl == nil {
|
|
err = .Invalid_File
|
|
return
|
|
}
|
|
|
|
impl := (^File_Impl)(f.impl)
|
|
iter.f = f
|
|
|
|
buf: [dynamic]byte
|
|
buf.allocator = file_allocator()
|
|
defer if err != nil { delete(buf) }
|
|
|
|
// NOTE: this is very grug.
|
|
for {
|
|
non_zero_resize(&buf, 512 if len(buf) == 0 else len(buf)*2) or_return
|
|
|
|
n, _err := wasi.fd_readdir(__fd(f), buf[:], 0)
|
|
if _err != nil {
|
|
err = _get_platform_error(_err)
|
|
return
|
|
}
|
|
|
|
if n < len(buf) {
|
|
non_zero_resize(&buf, n)
|
|
break
|
|
}
|
|
|
|
assert(n == len(buf))
|
|
}
|
|
iter.impl.buf = buf[:]
|
|
|
|
iter.impl.fullpath = make([dynamic]byte, 0, len(impl.name)+128, file_allocator()) or_return
|
|
append(&iter.impl.fullpath, impl.name)
|
|
append(&iter.impl.fullpath, "/")
|
|
|
|
return
|
|
}
|
|
|
|
_read_directory_iterator_destroy :: proc(it: ^Read_Directory_Iterator) {
|
|
delete(it.impl.buf, file_allocator())
|
|
delete(it.impl.fullpath)
|
|
it^ = {}
|
|
}
|